Long ago, I created a package for handling “Complex Buttons” – that is buttons that remain selected until another button in the same “group” is selected. In a nutshell, the developer creates a class that describes visual states of his button and implements the interface IComplexButton. These classes are wrapped inside a ComplexButton instance. Several of these ComplexButton instances are then passed to a Menu class (which is finally added to the display list) which handles all mouse interaction (rollovers, dragovers, clicks, release outsides, etc) and maintains button state. For more information and some downloads, check out this old post over at Kirupa.com.
Why do I blather on about all this, you ask? Well, when I was trying to create an Accordion widget to use in my ASDoc Gui (post before this), I thought this little Complex Button “framework” (for lack of better term) would be just the way to go. Well, I was right and I was wrong. It turns out that the way I had written the ComplexButton class it would not work for an accordion (for starters, it disables mouse communication with its children – something you definitely look for in an accordion. It just went downhill from there.). Well after an hour or two of mucking about with the ComplexButton class, I finally just copied and pasted the whole schmeer into a new .as file, deleted what I didn’t want and added what I did. This is a horrible horrible coding practice. It should have been extended, encapsulated, or something. Instead I now have two nearly identical classes with nearly identical function – ComplexButton and ComplexAccordionButton – residing in the same package. Ouch. Lesson learned: ALWAYS design with extension in mind. It’s not just something you read in all the hot titles.
Anyway, that coding architecture faux pas aside, I now have a very nice Accordion widget added to my ui package that I shared earlier. A straight out of the box, no frills version looks something like this:
And with a simple dose of customization, you could make something like this:
Both of these examples come from this simple script (just uncomment/recomment the lines for the basic or fancy accordion):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
package { import com.onebyonedesign.ui.OBO_Accordion; import flash.display.Sprite; import flash.filters.DropShadowFilter; import flash.text.TextField; import flash.text.TextFieldAutoSize; /** * Example usage of OBO_Accordion class * @author Devon O. */ public class AccordionTest extends Sprite { private var _accordion:OBO_Accordion; public function AccordionTest():void { var content1:Sprite = createContent(); var content2:Sprite = createContent(); var content3:Sprite = createContent(); var accordionInfo:Array = new Array( { label:"Content One", content:content1 }, { label:"Content Two", content:content2 }, { label:"Content Three", content:content3 } ); // basic accordion _accordion = new OBO_Accordion(accordionInfo); // fancy pants accordion //_accordion = new OBO_Accordion(accordionInfo, 200, 350, 20, 0x4B4B4B, 0x292929, "_typewriter", 11, 0xFFFFFF, true); //_accordion.filters = [new DropShadowFilter()]; _accordion.x = int(stage.stageWidth * .5 - _accordion.width * .5); _accordion.y = int(stage.stageHeight * .5 - _accordion.height * .5); addChild(_accordion); // getItemAt() method allows access to Accordion content _accordion.getItemAt(0).getChildByName("textField").text = "This is text added after accordion creation."; } /** * Just creates a randomly colored sprite as test content */ private function createContent():Sprite { var content:Sprite = new Sprite(); content.graphics.beginFill(Math.random() * 0xFFFFFF); content.graphics.drawRect(0, 0, 350, 200); content.graphics.endFill(); var tf:TextField = new TextField(); tf.autoSize = TextFieldAutoSize.LEFT; tf.x = tf.y = 25; tf.name = "textField"; tf.text = "This is text added during content creation."; content.addChild(tf); return content; } } } |
If interested, you can download the new ui package here. It includes all the classes from the last post, plus the accordion, plus the complex button package, plus documentation.
Incidentally, the Accordion requires Tweener for its animation, but you're welcome to re-write the AccordionSection.as file to use whatever tweening package you're most comfortable with. Me, I like Tweener.
Hope this may help some folks out...
Nice work, thanks for the download!
Howdy, Devon. Nice job, once again, with the OBO components. I’m using the accordion here and was wondering if you could provide me with some direction on how to go about having all the panels initially closed instead of the first one starting opened. I don’t need a detailed tutorial, but perhaps you could point me in the right direction or pass along some general thoughts on how you’d approach that.
I’ve been digging through the source but haven’t yet discovered a solution. Your insight is appreciated.
Cheers!
Hey Skye,
In the OBO_Accordion.as class file, in the init() method, comment out the line _menu.selected=”0″; and see if that works for you. In any case, thank you for the comments..
d.
How embarrassingly obvious. :)
Many thanks, Devon. If you pass me your email I’ll send you a link off-blog to how I’m using it on a site in-progress. You might like a couple of the tiny visual mods I made.
Best,
Skye
I’d definitely like to see it. You can just use webmaster AT onebyonedesign DOT com to send a link. I’m glad that helped out…
Really nice work Devon O! I’m sorry this is a little off piste for this post but I couldn’t find your original post on ComplexButtons.
I’m trying to create an accordion menu which is almost exactly the same as this except it uses XML to create the buttons. To separate Main from Sub I’ve labeled them in the name property. Now all I need to do is manage their various rollover states using your ComplexButton class. This should be simple right!? : ) but I’m having trouble getting it to work. The sub button event triggers the main button event. I feel like I’m nearly there but would you mind helping me over the last hurdle?
Hey jim, without seeing any script, it looks as though you need to set something’s mouseEnabled or mouseChildren property to false. Just kind of a shot in the dark, but that’s what the symptoms sound like…
Hey Devon O, Thanks for your reply. Yeah I tried setting mouseChildren = true it was set to false in the ComplexButton Class, this does help activate rollover conditions on the subMenus but it doesn’t manage the selected status. It seems like the mask I’ve used to reveal the subMenus which are attached to a parent Main Menu clip is catching both Main & Sub mouseEvents. I’ve tried setting the mask to mouseEnabled = false but it has no effect. I think it’s inheriting this property from the parent clip. I’ve also been trying to name each clip Main & Sub then filtering events accordingly in your class but I’m finding this mask still catches my mouseevents. hmm, I’m stumped! I’m happy to send you the code but there is a lot of it! I dunno if it would be easier for you to try a similar test at your end?
Is this available in AS2 and/or an code implementation example available to integrate it?
Hey James,
It’s not available in AS2, but there is a usage example in the asdocs. http://www.onebyonedesign.com/flash/ui/docs/