Swapping Accordion Header Icons

Without going into all the specifics of how to create an accordion in Flash (you can see more about that here), I had a need for the ability to swap out an icon that appears in the header (see figure 1 below) after the accordion had already been rendered to the stage. I looked all over the place for documentation on how to accomplish this, however with no luck. Maybe I'm blind, maybe my search abilities just suck, but whatever the case I finally gave up and decided to dig into the classes and see if I could find anything.

The problem is that there’s no documentation I could find that shows how to target the icon, but after a bit of search I finally found a way to target the headers of the accordion by using "_header" followed by the position number of the header (e.g. _header0 to reference the first header, _header1 to reference the second header, etc...).

For example if I wanted to swap out the icon* in the first header of my accordion at the press of a button, I could use the following code:

Figure 1:
Standard icon set

Code:
myButton.onRelease = function() {
myAccordion._header0.icon = 'bombIcon';
}

Figure 2:
Alternate icon

*Note: make sure your icons are in your library and the linkage is set to export in the first frame, and use that linkage name when specifying the icon ('bombIcon' in the code example above)

Hopefully this saves someone else (and possibly me) time searching for this solution in the future :D

41 Responses to “Swapping Accordion Header Icons”

  1. ericd Says:

    i found that out about a year ago when i needed to use carrot icons (like tree) and did something similar. I made a listener inside which checks for the active item, and adjusts its icon & the others.

    cool :)

  2. Crucial Says:

    yeah it was one of those “I know its possible” but man no matter where I looked I couldn’t find anything. Figured I better document it somewhere for myself atleast :D

  3. JesterXL Says:

    Crucial set accordion up the bomb
    we get icon

  4. Crucial Says:

    [...]Crucial set accordion up the bomb
    we get icon[...]

    Damn…I left my super-secret-agent decoder ring at home…

  5. Philippe maegerman Says:

    Another way to achieve this:
    myAccordion.getHeaderAt(0)['icon'] = ‘bombIcon’;

  6. Jason Says:

    Is there anyway to move the label of the accordion header? Or do you need to have your icons a certain size for it to look proper.

    My Icons are 20 x 20 but the text for the header is aligned to the top.

    Thanks for any help.

  7. Denyo Says:

    Is it possible to adress the Headers over, click … status?

    myAccordion.header0.onRollOver = function () { trace(“something”);} doesn’t work!

    Denyo

  8. Crucial Says:

    your close with what you have, however you have to implement a few more things to get it all to work.

    First you need to use a [b]doLater()[/b] method that sets the mouseEvents after the accordion has initialized and been drawn to the screen.

    Next you’ll want to make sure you call the super() method on the header as well so that you dont break the even model that come with the component.

    For exmaple, lets assume I have an accordion on my stage with an instance name of myAccordion. I’ll create a loop to make sure I get all of the headers and add in a trace for the onRelease and onRollOver states. See my example below:

    function setActions() {
    var headerCount:Number = myAccordion.numChildren;
    for (var i:Number = 0; i < headerCount; i++){
    myAccordion["_header"+i].onRollOver = accOver;
    myAccordion["_header"+i].onRelease = accRelease;
    }
    }
    function accOver() {
    // do RollOlver stuff
    super.onRollOver();
    trace("Rolled Over "+this.label);
    }
    function accRelease() {
    // do Release stuff
    super.onRelease();
    trace("Released "+this.label);
    }
    myAccordion.doLater(this, "setActions");

    Hope that helps,
    -Dave

  9. Denyo Says:

    Great stuff, Dave!

    Though I had to complete your “for()-loop”, it finally helped perfect! Thx for that!

  10. Crucial Says:

    My bad, hazard of typing in a comment box and not in SE|PY. All fixed now :)

    Glad I could help,
    -Dave

  11. guangming Says:

    how can I reposition the icon and attach an event to it in the header?

    I would like to put the icon at the right side and to click the icon to do something else.

    thanks,

    Guangming

  12. Robert Nikolic Says:

    Is there any way to have the hand cursor appearing when you rollOver one of the accordion headers?
    thanks, Robert

  13. Crucial Says:

    @Robert – to enable the hand cursor on the headers, in your rollover method (see comment above) add the following line of code this.useHandCursor = true;

  14. Luke Says:

    Hey there,

    What about moving and accessing accordion header labels, as in this post?

    “Is there anyway to move the label of the accordion header? Or do you need to have your icons a certain size for it to look proper. My Icons are 20 x 20 but the text for the header is aligned to the top.”

    I need to do this urgently….

    Cheers, Luke

  15. Crucial Says:

    @Luke – you can adjust the text indent by using the following inside the doLater method described above:
    // set autosize first so our label doesnt get chopped off
    myAccordion["_header0"].labelPath.autoSize = true;
    // next set the textIndent property of the text field
    myAccordion["_header0"].textIndent = 40;

    However to adjust the vertical alignment takes a bit more work and a ton of hacking as the y for the label gets reset on rollover/release, etc.. Probably not worth it in my opinion.

  16. Luke Says:

    Thanks for the reply. Is there anyway to get around this? It’s a pretty major limitation of the component if you can alter the header height but they’re not vertically centred. What about applying some additional leading to the font style or something?

    Cheers

  17. Crucial Says:

    @luke – I agree , that is a limitation. I have not had the need to do that to be honest but could definitely see a reason to alter the padding. Off the top of my head, I assume you’d need to alter the _y property of the labelPath (textField) object. However you’ll have to set a timer to initially changes the header text position after it has been drawn to the stage. Then you’d have to also set the _y on rollover / release / rollout / dragout / dragover .

    Again this is all assumptions on my part as I have not investigated this option at all. You might also consider looking into the Bit component set over at Flash Loaded they have an accordion in that set and I understand they are easily configured.

  18. Luke Says:

    OK thanks for your help.

  19. Robert Nikolic Says:

    Great tips!
    I hace accordion with 6 children. Is there a way to force the accordion to open tab No4 when accessing the webpage?

    Many thanks, Robert

  20. Crucial Says:

    Thanks Robert. Yes you can set the selectedIndex property of the accordion. In your example (6 accordion panes, and you want it to default open on pane/child 4), assuming the instance name of your accordion was “myAccordion” you could use the following code:
    myAccordion.selectedIndex = 3;
    Remember: the accordion panes (children) are numbered like an array using a zero based index (i.e. numbering starts at 0, not 1).

    Hope that helps.

  21. mindilator Says:

    Luke, try setting an AccordionHeaderSkin and be sure that the skin movie clip has more than a shape in there. I had the same problem with header text aligning to the top, until I changed the skin from a shape to a graphic instance. After that, it aligned vertically centered nicely.

    I tried setting the _y of the labelPath as well as using the move() function, inside enterFrame events, but the accordion kept resetting the y value to default on any event change. As a result you could see the position change, and then jump back. After placing the move() on the enterFrame event I tried increasing the frame rate (my application only has one frame, so I’m ok timeline-wise). At 100fps I got a nasty flickering, though the positioning I wanted stayed put a little better. Anything over 100fps and the accordion wouldn’t populate at all.

  22. Robert Says:

    Please help me i have tried everything to get this code to work, it simply just does want to work after 4 hours here at work , paid by the hour and nothing happening, and i know there is probably a missing peice, but this is what i have, i just want it to change the icon immediately, upon accessing the frame, so i put the following code at frame 1 of my movie

    my_acc._header0.icon = 'fm_cb_intro_checked';
    my_acc._header0.selectedChild.icon = 'fm_cb_intro_checked';
    my_acc["_header0"].icon = 'fm_cb_intro_checked';

    please respond with any help

  23. Crucial Says:

    Robert, you need to make sure your setting the icon in the doLater method as described above. Here’s a file you can take a look at to see how the icons can be set and manipulated.

    Hope that helps

  24. Robert Q. Says:

    Thanks again for the help, although pasting the code into the frame(15) i needed to change the icon upon reaching frame 15, did not work initially im convinced it had to be something i messed up along the way of initially creating the menu outside of the movieclip i am calling it from, perhaps that confuses the actionscript (in the way a relative/absolute target might). (and yes i modified the code properly to point directly to my_acc which is my accordion) (i even added the other 3 lines of code i had before in places that would be activated upon viewing the frame 15)

    I am going to modify your compontent to access my movieclips as sub menu items and make the call from the top top top layer, just to test it, even tho i must access it from inside of the real movieclip that displays the screens/pages, and not the movieclip displaying the menu, and not the top layer. sorry if that was confusing.

    One last thing, can you please re-upload the file to a simpler encoded format, i have MS Word XP, and it says i cant open your file without installing another feature, and i dont have the installation dvd anywhere near me. Perhaps a .RTF or even .txt or a .php style generic format would work.

    If not, its ok, my understanding is that those are just additional functions, and not core functions needed for me to change the icon.

  25. Crucial Says:

    The file I uploaded was a .fla (native Flash file) not a text file. If your just looking for the code here’s what I have:

    function setActions() {
    	var headerCount:Number = myAccordion.numChildren;
    	for (var i:Number = 0; i < headerCount; i++) {
    		myAccordion["_header"+i].onRollOver = accOver;
    		myAccordion["_header"+i].onRelease = accRelease;
    		myAccordion["_header"+i].icon = 'icon';
    	}
    }
    function accOver() {
    	// do RollOlver stuff
    	super.onRollOver();
    	trace("Rolled Over "+this.label);
    	//this.useHandCursor = true;
    }
    function accRelease() {
    	// do Release stuff
    	super.onRelease();
    	trace("Released "+this.label);
    	this.icon = 'selectedIcon';
    }
    myAccordion.doLater(this, "setActions");
    myAccordion.selectedIndex = 2;

    As for your issue, make sure your accordion is on the stage when the code executes and it should work just fine.

    Hope that helps,
    -Dave

  26. Robert Q. Says:

    oh your right, i am sorry, ive seen so many people claiming to fix this issue that i confused you with a different site, they had a .doc file that described all the possible functions and ways to access the accordion. (doesnt work with word xp for some reason without extra features)

    im sorry, too many sleepless nights on this one lol.

    thanks again, im going to test out that code now.

    oh also if your curious what code i was using, this was what i pasted into frame 20 (not 15 sorry lol)

    function setActions() {
         var headerCount:Number = my_acc.numChildren;
    for (var i:Number = 0; i

    what i was thinking i did wrong, is i needed to move the do later stuff to frame 1, except i actually needed to put “fm_cb_intro_Checked” lines inside of a function, which i would access those functions later i suppose from frame 20.

    i apologize if that all sounded wrong, but from a php programming stand point, this is very strange trying to work inside of different frames, and calling from other frames, also from inside and outside of movieclip levels. i’m trying really hard to figure out what mistakes i’m making.

    like if i applied this logic to php, a frame would be a different web page completely, and i would have chosen to do the “function sets” on the top most frame (aka the page that does the -include/require once-) type of stuff. there for enabling me to call that function from inside of the included pages.

    but trying to see that in action script is just not so obvious, i know i am on the right path too.

    oh also ifigured out what happened, that .fla was turning into a .doc file upon download, that is so strange, ive never seen that before. its just my computer cuz at work it downloaded fine, sorry again about that, like i said, ive just looked at so many solutions i get confused, but that fla file you uploaded definetly works, thank you for the code, i will make it work on mine =) , thank you for your hard work.

    ok i figured out the problem, one of my initial thoughts, it wasnt targetting it properly.

    I know you said the object had to be on the stage, but my accordion wasnt just on the stage, it was inside of 3 movie clips, animating it.

    Since i dont know how yet to target strictly inside of action script, without using the target method, i will instead attempt to just have all of the actions inside of the menu movie clip itself, and just tell it to go to frame 5 if it needs to check that particular box, and the action will tell that specific one to check.

    they are asking me to make a quiz, which is in an entirely different movie clip, however, using the root_ method, i can tell that accordion’s movie clip to go to a frame which tells it to check the box corresponding to that section, and check mark it =)

    I may not have all the keys, but i found me a door and im building me a house ! =) with sticks >_> … bamboo sticks !

    thanks again for all your help, you saved me =) and i owe you greatly, and i will pass on the knowledge to those i come across.

    p.s. yes it does really work =)

    **10-13-08 combined multiple posts – Admin

  27. Dean Says:

    This is fantastic info. Thanks very much for posting it. One question: is it possible to instead of having the icons change when clicked, simply have one icon for an open header, and another one for the closed ones? I was able to make the icon change when clicked, but I need to others to reset to the default icon when a new section is opened.

  28. Crucial Says:

    @dean sure you just need to loop through the headers and reset them to the icon you want without changing the selected one. for example something like

    function resetIcons() {
    	var headerCount:Number = myAccordion.numChildren;
    	for (var i:Number = 0; i<headerCount; i++) {
    		if(myAccordion.selectedIndex != i){
    			myAccordion["_header"+i].icon = 'icon';
    		}
    	}
    }

    Should do the trick.

  29. Dean Says:

    So does that replace the setActions function? Here’s what I’ve got now and it’s not quite right:

    function setActions() {
    	var headerCount:Number = myAccordion.numChildren;
    	for (var i:Number = 0; i<headerCount; i++) {
    		myAccordion["_header"+i].onRelease = accRelease;
    		myAccordion["_header"+i].onRollOver = accOver;
    		myAccordion["_header"+i].icon = 'arrow';
    	}
    }
     
    function accOver() {
    	super.onRollOver();
    	trace("Rolled Over "+this.label);
    	this.useHandCursor = true;
    	this.icon = 'arrowDown';
    }
     
    function accRelease() {
    	super.onRelease();
    	trace("Released "+this.label);
    	this.icon = 'arrowDown';
    }
     
    function resetIcons() {
    	var headerCount:Number = myAccordion.numChildren;
    	for (var i:Number = 0; i<headerCount; i++) {
    		if (myAccordion.selectedIndex != i) {
    			myAccordion["_header"+i].icon = 'arrow';
    		}
    	}
    }
    myAccordion.doLater(this,"setActions");
    myAccordion.selectedIndex = 0;
  30. Crucial Says:

    @Dean no you can keep it the same as before and just add a method. Something like this:

    function setActions() {
    	var headerCount:Number = myAccordion.numChildren;
    	for (var i:Number = 0; i < headerCount; i++) {
    		myAccordion["_header"+i].onRollOver = accOver;
    		myAccordion["_header"+i].onRelease = accRelease;
    		myAccordion["_header"+i].icon = 'arrow';
     
    	}
    }
     
    function accOver() {
    	// do Rollover stuff
    	super.onRollOver();
    	trace("Rolled Over "+this.label);
    	this.icon = 'arrowDown';
    }
     
    function accRelease() {
    	// do Release stuff
    	super.onRelease();
    	trace("Released "+this.label);
    	this.icon = 'arrowDown';
    	resetIcons()
    }
     
    function resetIcons() {
    	var headerCount:Number = myAccordion.numChildren;
    	for (var i:Number = 0; i < headerCount; i++) {
    		if(myAccordion.selectedIndex != i){
    			myAccordion["_header"+i].icon = 'arrow';
    		}
    	}
    }
     
    myAccordion.doLater(this, "setActions");
    myAccordion.selectedIndex = 0;
    resetIcons();
  31. Dean Says:

    Thanks a bunch. The Adobe documents are pretty much worthless when it comes to accordion components, so this will help a lot of folks. Cheers.

  32. dotpitch Says:

    Hy Guys, could you please tell me how could i change the color of the Label on rollOver? I can´t find the right Path.

    Hope you could help me out.

    Greetz

  33. Crucial Says:

    @dotpitch okay that took a bit of digging but I think I have it figured out. Basically you need to set a text format for the label color when you set up the accordion then on rollover/rollout reset the text format then reapply the color after the super method executes. For example:

    var labelColor:Number = 0x57B517;
    var overColor:Number = 0xff0000;
     
    function setActions() {
    	var headerCount:Number = myAccordion.numChildren;
    	for (var i:Number = 0; i<headerCount; i++) {
    		myAccordion["_header"+i].onRollOver = accOver;
    		myAccordion["_header"+i].onRollOut = accOut;
    		myAccordion["_header"+i].onRelease = accRelease;
    		myAccordion["_header"+i].icon = 'icon';
    		myAccordion["_header"+i].labelPath.setStyle("color", labelColor);
    	}
    }
    function accOver() {
    	// do RollOver stuff
    	labelPath.setStyle("color", overColor);
    	super.onRollOver();
    	trace("Rolled Over "+this);
    	this.labelPath.textColor = overColor;
    }
    function accOut() {
    	// do RollOut stuff
    	labelPath.setStyle("color", labelColor);
    	super.onRollOut();
    	trace("Rolled Out "+this);
    	this.labelPath.textColor = labelColor;
    }
    function accRelease() {
    	// do Release stuff
    	super.onRelease();
    	trace("Released "+this.label);
    	this.icon = 'selectedIcon';
    	resetIcons()
    }
    function resetIcons() {
    	var headerCount:Number = myAccordion.numChildren;
    	for (var i:Number = 0; i<headerCount; i++) {
    		if(myAccordion.selectedIndex != i){
    			myAccordion["_header"+i].icon = 'icon';
    		}
    	}
    }
    myAccordion.doLater(this, "setActions");
    myAccordion.selectedIndex = 2;
    resetIcons();

    Hope that helps,
    -Dave

  34. dotpitch Says:

    Cool! That really Helps!! Thank You!

    Chrischan

  35. dotpitch Says:

    Hey Dave, just one more Question about the Accordion.

    Is it possible that the Childs fit to the Content of it? Every Child has the same height that suckz =)

    Regardz Chrischan

  36. Crucial Says:

    You can resize the component using setSize(); So what you could probably do is get the height of the child then resize the component accordingly.

  37. beerland Says:

    I think I just saved myself a night of hair pulling by finding this page. Only took me three queries in google, too. Excellent stuff, thanks!

  38. Mauricio Hernández Says:

    I made an implementation and fully customization of this component the only thing that i didn’t have, was the hand cursor but with your article was solved, very good article into the deep world of the accordion component of flash

  39. DeadDuck Says:

    The stock Accordion component is too limited without having some kind of workaround, and Adobe’s help documentation doesn’t help a bit.

    I’ve been trying to get this accordion thing to work, where I want all the panes to be closed initially. By Default, the first pane of Accordion instance will be in open state unless specified some other pane using SelectedIndex parameter. I can’t seem to get it working… worse, when to open certain pane, clicking on the header again won’t close it back.

    Any idea guys?

  40. Neil Says:

    Hi, some great stuff on here. I am wanting to have a different colour for each pane in the Accordion, any ideas how to achieve this?
    Cheers

  41. windy Says:

    I want to get the – image when I click on the + image which are present in the header of the Accordion with only one pane.
    Can any one suggest me the solution with Jscript that is to be used in .net

Leave a Reply


Visit Portfolio :

Crucial Limit

Client List :

Aces Tattoos | 82 Tattoo | Eric Peacock | Kustom Tattooz | Laser Imaging & Design | Laterras R. Whitfield | Solipsum | Travelocity ExperienceFinder {beta} | Travelocity | ZSI

Socialize:

Flickr | View Dave Gillem's LinkedIn profileView my LinkedIn profile | Twitter | Facebook | Become a fan of Crucial Limit on Facebook Become a fan on Facebook

Add to: