How to: XML based menu system from lithinos.com
I'm adding this thread as a way of answering the questions about how to 'create' a menu using XML and Flash.
I'm not very familiar with other menu systems, so I can't help with any of the others...
PHP Code:
/*
************************
* XML based menu
* Richard Lyman
* Support thread:
* [url]http://www.flashkit.com/board/showthread.php?threadid=416761[/url]
************************
Aside from this menu, you'll need to have a symbol exported from the library.
The symbol needs to contain:
- A text box with the instance name: "display"
- (optional) A 'level-change-indicator' with the instance name: "pointer"
The symbol needs to be exported under the name:
- "option"
Optional:
- A 'breadcrumbs' named instance of a text box
- A 'mainDisplay' named instance of a text box
- A 'scroller' named instance of the scrollbar component
*/
_root . mainDisplay . html = true ;
_root . breadcrumbs . html = true ;
_root . breadcrumbBasket = new Array();
_root . maxX = 10 ;
_root . maxY = 380 ;
_root . scroller . onEnterFrame =function(){
_root . mainDisplay . maxscroll > 1 ? this . _visible = 1 : this . _visible = 0 ;
}
_root . createEmptyMovieClip ( "menuReset" , 7000 );
_root . menuReset . onEnterFrame =function(){
if(! _root . navigatingMenu ){
_root . counter ++;
if( _root . counter > 15 ){
hideOtherSubMenus ( "main" , 10 );
_root . counter = 0 ;
}
}
}
myXML = new XML ();
myXML . onLoad =function ( status ){ status ? parseXML () : _root . output . text = "XML parsing failed" };
myXML . load ( "site.xml" );
function parseXML (){
_root . setupMenu ( _root . myXML , - 90 , 0 , "none" );
_root . populateDisplay ( "main" );
}
function hideOtherSubMenus ( pID , xPos ){
if( pID == "main" ) _root . main . pointer . _visible = 0 ;
for( i in _root ){
if(( _root [ i ]. parentID == pID ) && ( _root [ i ]. _x == xPos )){
_root [ i ]. pointer . _visible = 0 ;
}else if(( _root [ i ]. parentID != pID ) && ( _root [ i ]. _x > xPos )){
_root [ i ]. removeMovieClip ();
}
}
}
function addBreadcrumb ( link ){
var bcID = _root . myXML [ link ]. attributes [ 'id' ];
var bcText = _root . myXML [ link ]. attributes [ 'displayText' ];
if( bcText == undefined ) bcText = bcID ;
_root . breadcrumbBasket . push ( bcID + "|" + bcText );
if( _root . breadcrumbBasket . length > 7 ) _root . breadcrumbBasket . splice ( 0 , 1 );
totalLink = "" ;
for( i in _root . breadcrumbBasket ){
var startLink = "<a href='asfunction:populateDisplay," ;
bcID = _root . breadcrumbBasket [ i ]. split ( "|" )[ 0 ];
bcText = _root . breadcrumbBasket [ i ]. split ( "|" )[ 1 ];
totalLink = startLink + bcID + "'>" + bcText + "</a>" + " | " + totalLink ;;
}
_root . breadcrumbs . htmlText = "" ;
_root . breadcrumbs . htmlText = totalLink ;
}
function removeBreadcrumb ( link ){
crumbLimit = _root . breadcrumbBasket . length ;
while( crumbLimit --){
if( _root . breadcrumbBasket [ crumbLimit ]. split ( "|" )[ 0 ]== _root . myXML [ link ]. attributes [ 'id' ]){
_root . breadcrumbBasket . splice ( crumbLimit , 1 );
}
}
}
function navigate ( link , originName ){
_root . yPos = 0 ;
_root [ link ]. pointer . _visible = 1 ;
_root . setupMenu ( _root . myXML [ link ], _root [ link ]. _x , _root [ link ]. _y - 20 , originName );
}
function populateDisplay ( selectedID ){
_root . removeBreadcrumb ( selectedID );
_root . mainDisplay . htmlText = _root . myXML [ selectedID ]. childNodes [ 1 ]. firstChild . nodeValue ;
_root . addBreadcrumb ( selectedID );
}
function createOption ( displayText , choiceID , previousOption , startX , startY ){
_root . next ++;
var n = choiceID ;
attachMovie ( "option" , n , _root . next );
_root [ n ]. pointer . _visible = 0 ;
_root [ n ]. display . text = displayText ;
_root [ n ]. parentID = previousOption ;
_root [ n ]. optionButton . onRollOver =function(){
_root . navigatingMenu = true ;
_root . counter = 0 ;
hideOtherSubMenus ( previousOption , _root [ n ]. _x );
_root . navigate ( choiceID , this . _parent . _name );
_root . showHint ( choiceID , this . _parent . _x , this . _parent . _y );
}
_root [ n ]. optionButton . onRollOut =function(){
_root . navigatingMenu = false ;
}
_root [ n ]. optionButton . onRelease =function(){
populateDisplay ( choiceID );
hideOtherSubMenus ( "main" , 10 );
_root . navigatingMenu = false ;
}
_root [ n ]. _x = startX + 95 ;
_root [ n ]. _y = startY + 20 ;
_root . maxX =( _root [ n ]. _x + 110 > _root . maxX ) ? _root [ n ]. _x + 90 : _root . maxX ;
_root . maxY =( _root [ n ]. _y - 40 < _root . maxY ) ? _root [ n ]. _y - 20 : _root . maxY ;
if( _root [ n ]. _y <= 20 ) {
_root . total ++;
_root [ n ]. _y += _root . total * 20 ;
for( i in _root ){
if( _root [ i ]. parentID == previousOption && _root [ i ] != _root [ n ]){
if( _root [ i ]. _name != "breadcrumbs" ){
_root [ i ]. _y += 20 ;
}
}
}
}
}
function setupMenu ( topNode , startX , startY , originName ){
_root . foundOption = false ;
for( i in topNode . childNodes ){
if( topNode . childNodes [ i ]. nodeName == "option" ){
var choiceID = topNode . childNodes [ i ]. attributes [ 'id' ];
var displayText = topNode . childNodes [ i ]. attributes [ 'displayText' ];
if( displayText == undefined ) displayText = choiceID ;
var previousOption = _root . myXML [ choiceID ]. parentNode . attributes [ 'displayText' ];
var previousID = _root . myXML [ choiceID ]. parentNode . attributes [ 'id' ];
if( previousOption == undefined ) previousOption = previousID ;
createOption ( displayText , choiceID , previousOption , startX , startY );
startY -= 20 ;
_root . foundOption = true ;
}
}
if(! _root . foundOption ){
_root [ originName ]. pointer . _rotation = 180 ;
}
_root . total = 0 ;
}
If you have questions on how to use this - ask me here...
Here's an example of the XML you'd use with that menu system:
PHP Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE option
[
<!ELEMENT content (#PCDATA)>
<!ELEMENT option (content, option*)>
<!ATTLIST option
id CDATA #REQUIRED
displayText CDATA #IMPLIED
>
]>
<option id="main_this_has_to_be_unique" displayText="NAVIGATION">
<content>Here is the first thing users can see...</content>
<option id="ruby_this_has_to_be_unique" displayText="ruby">
<content>This section would be abut Ruby</content>
<option id="subMenu_this_has_to_be_unique" display="ruby sub menu">
<content></content>
</option>
</option>
<option id="ocaml_this_has_to_be_unique" displayText="ocaml">
<content>If you had a lot to say...
... and you wanted each line to be on it's own...
... then you could just add it to the XML...
</content>
</option>
<option id="udfug_this_has_to_be_unique" displayText="U.D.F.U.G.">
<content><![CDATA[Since this section is inside a CDATA tag, it can have a link to <a href="udfug.org">udfug.org</a>]]></content>
</option>
<option id="myServers_this_has_to_be_unique" displayText="myServers">
<content><![CDATA[CDATA tags can even allow you to call functions defined in your SWF... say to display the <a href="asfunction:populateDisplay,main_this_has_to_be_unique">the top</a> of this menu]]></content>
</option>
</option>
Here's a version of the menu that auto expands each submenu to the length of the longest displayText
PHP Code:
_root . mainDisplay . html = true ;
_root . breadcrumbs . html = true ;
_root . breadcrumbBasket = new Array();
_root . maxX = 10 ;
_root . maxY = 380 ;
_root . scroller . onEnterFrame =function(){
_root . mainDisplay . maxscroll > 1 ? this . _visible = 1 : this . _visible = 0 ;
}
_root . createEmptyMovieClip ( "menuReset" , 7000 );
_root . menuReset . onEnterFrame =function(){
if(! _root . navigatingMenu ){
_root . counter ++;
if( _root . counter > 15 ){
hideOtherSubMenus ( "main" , 10 );
_root . counter = 0 ;
}
}
}
myXML = new XML ();
myXML . onLoad =function ( status ){ status ? parseXML () : _root . output . text = "XML parsing failed" };
myXML . load ( "site.xml" );
function parseXML (){
_root . setupMenu ( _root . myXML , 0 , 0 , "none" );
_root . populateDisplay ( "main" );
}
function hideOtherSubMenus ( pID , xPos ){
if( pID == "main" ) _root . main . pointer . _visible = 0 ;
for( i in _root ){
if(( _root [ i ]. parentID == pID ) && ( _root [ i ]. _x == xPos )){
_root [ i ]. pointer . _visible = 0 ;
}else if(( _root [ i ]. parentID != pID ) && ( _root [ i ]. _x > xPos )){
_root [ i ]. removeMovieClip ();
}
}
}
function addBreadcrumb ( link ){
var bcID = _root . myXML [ link ]. attributes [ 'id' ];
var bcText = _root . myXML [ link ]. attributes [ 'displayText' ];
if( bcText == undefined ) bcText = bcID ;
_root . breadcrumbBasket . push ( bcID + "|" + bcText );
if( _root . breadcrumbBasket . length > 7 ) _root . breadcrumbBasket . splice ( 0 , 1 );
totalLink = "" ;
for( i in _root . breadcrumbBasket ){
var startLink = "<a href='asfunction:populateDisplay," ;
bcID = _root . breadcrumbBasket [ i ]. split ( "|" )[ 0 ];
bcText = _root . breadcrumbBasket [ i ]. split ( "|" )[ 1 ];
totalLink = startLink + bcID + "'>" + bcText + "</a>" + " | " + totalLink ;;
}
_root . breadcrumbs . htmlText = "" ;
_root . breadcrumbs . htmlText = totalLink ;
}
function removeBreadcrumb ( link ){
crumbLimit = _root . breadcrumbBasket . length ;
while( crumbLimit --){
if( _root . breadcrumbBasket [ crumbLimit ]. split ( "|" )[ 0 ]== _root . myXML [ link ]. attributes [ 'id' ]){
_root . breadcrumbBasket . splice ( crumbLimit , 1 );
}
}
}
function navigate ( link , originName ){
_root . yPos = 0 ;
_root [ link ]. pointer . _visible = 1 ;
_root . setupMenu ( _root . myXML [ link ], ( _root [ link ]. _x + _root [ link ]. _width ), _root [ link ]. _y - 20 , originName );
}
function populateDisplay ( selectedID ){
_root . removeBreadcrumb ( selectedID );
_root . mainDisplay . htmlText = _root . myXML [ selectedID ]. childNodes [ 1 ]. firstChild . nodeValue ;
_root . addBreadcrumb ( selectedID );
}
function createOption ( displayText , choiceID , previousOption , startX , startY , maxSizeOfSet ){
_root . next ++;
var n = choiceID ;
attachMovie ( "option" , n , _root . next );
_root [ n ]. pointer . _visible = 0 ;
_root [ n ]. display . autoSize = "left" ;
_root [ n ]. display . text = displayText ;
_root [ n ]. optionButton . _width = maxSizeOfSet + 8 ;
_root [ n ]. pointer . _x = _root [ n ]. optionButton . _width + 2.5 +( _root [ n ]. pointer . _width / 2 );
_root [ n ]. parentID = previousOption ;
_root [ n ]. optionButton . onRollOver =function(){
_root . navigatingMenu = true ;
_root . counter = 0 ;
hideOtherSubMenus ( previousOption , _root [ n ]. _x );
_root . navigate ( choiceID , this . _parent . _name );
_root . showHint ( choiceID , this . _parent . _x , this . _parent . _y );
}
_root [ n ]. optionButton . onRollOut =function(){
_root . navigatingMenu = false ;
}
_root [ n ]. optionButton . onRelease =function(){
populateDisplay ( choiceID );
hideOtherSubMenus ( "main" , 10 );
_root . navigatingMenu = false ;
}
_root [ n ]. _x = startX ;
_root [ n ]. _y = startY + 20 ;
_root . maxX =( _root [ n ]. _x + 110 > _root . maxX ) ? _root [ n ]. _x + 90 : _root . maxX ;
_root . maxY =( _root [ n ]. _y - 40 < _root . maxY ) ? _root [ n ]. _y - 20 : _root . maxY ;
if( _root [ n ]. _y <= 20 ) {
_root . total ++;
_root [ n ]. _y += _root . total * 20 ;
for( i in _root ){
if( _root [ i ]. parentID == previousOption && _root [ i ] != _root [ n ]){
if( _root [ i ]. _name != "breadcrumbs" ){
_root [ i ]. _y += 20 ;
}
}
}
}
}
function setupMenu ( topNode , startX , startY , originName ){
_root . textFieldWidth = 0 ;
maxSizeOfSet = 0 ;
for( i in topNode . childNodes ){
if( topNode . childNodes [ i ]. nodeName == "option" ){
var testText = topNode . childNodes [ i ]. attributes [ 'displayText' ];
if( testText == undefined ) testText = topNode . childNodes [ i ]. attributes [ 'id' ];
_root . attachMovie ( "option" , "test" , 23456 );
_root . test . display . autoSize = "left" ;
_root . test . display . text = testText ;
_root . test . _x = 0 ;
_root . test . _y =- 50 ;
if ( _root . textFieldWidth < _root . test . display . textWidth ){
_root . textFieldWidth = _root . test . display . textWidth ;
}
}
}
maxSizeOfSet = _root . textFieldWidth ;
_root . foundOption = false ;
for( i in topNode . childNodes ){
if( topNode . childNodes [ i ]. nodeName == "option" ){
var choiceID = topNode . childNodes [ i ]. attributes [ 'id' ];
var displayText = topNode . childNodes [ i ]. attributes [ 'displayText' ];
if( displayText == undefined ) displayText = choiceID ;
var previousOption = _root . myXML [ choiceID ]. parentNode . attributes [ 'displayText' ];
var previousID = _root . myXML [ choiceID ]. parentNode . attributes [ 'id' ];
if( previousOption == undefined ) previousOption = previousID ;
createOption ( displayText , choiceID , previousOption , startX , startY , maxSizeOfSet );
startY -= 20 ;
_root . foundOption = true ;
}
}
if(! _root . foundOption ){
_root [ originName ]. pointer . _rotation = 180 ;
}
_root . total = 0 ;
}
I forgot to mention, if you want the expanding menu to work with a specific font.. you need to 'embed fonts' in the symbol 'option's text field 'display'
... you'll probably also want to shrink the contents of the 'option' symbol so that they can expand to where they should be.. since they aren't made to 'shrink' to where they should be...
Senior Member
I don't have a zipped version... but you can just cut-n-paste the code and XML I've placed in this thread.
Not PWD
Hey, mind putting up a example?
And I'm glad to see you took my advice on the sticky thread.
PAlexC: That's just Chuck Norris's way of saying sometimes corn needs to lay the heck down.
Gerbick: America. Stabbing suckers since Vespucci left.
When you say putting up an example... since Code etc. is already here... you mean a working example of what the code does?
I've attached a Zip file of a FLA, SWF, and XML.
The code I posted probably won't match the code in the FLA...
Attached Files
Posting Permissions
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
Forum Rules
Click Here to Expand Forum to Full Width