Xml menu: onrollover declared in loop not working

Can somebody please help me with the following 'cause I’m confuesd, or overlooking something completely…

I’m building a small XML menu where I want to call a function for each subitem’s onrollover

part of my code:

[AS]
//*** build submenu items ****
for (j=0; j< numSubItems; j++){
curSubItemName = my_XML.firstChild.childNodes*.childNodes[j].firstChild.nodeValue;
curSubItem = root[“item”+i].createEmptyMovieClip("subItem"+i+"_"+j, myDepth);
curSubItem._y = (j+1)*-spacing;
myDepth++;
curSubItem.onRollOver = function(){
this.subHighLight();
}
}
[/AS]
and the subHighLight function for now just looks like this:
[AS]
MovieClip.prototype.subHighLight = function(){
trace(“test”);
};
[/AS]

The menu gets populated from the XML file, no problem. However, the onRollOver simply isn’t working, but why???

Thanks.

It should work. Can we see your fla ?

Sure. It’s HERE

I see the problem. It’s because you already have an onRollOver for the section movieclip. That rollOver disables the rollOver of the movieclips inside of it.

Hmn … you could fix this by using an onEnterFrame handler and hitTest on the section movieclips to check if they are being rolled over … but maybe that uses more resources than you’d like it to. What do you say ?

Hmm, I see… thanks :thumb:

And yes, preferrably I would not have an OnEnterFrame handler running continuousy, but only when needed, so that leaves me with a problem :frowning:

How about if I change the subitems to buttons instead of movieclips? Would that make a difference??

No, because their rollover will also be dominated by the rollover of the movieclip they’re in.

And yes, preferrably I would not have an OnEnterFrame handler running continuousy, but only when needed, so that leaves me with a problem

Yeah, kinda …

In that case I will have to think a little bit harder to come up with another solution.
Anyway, thanks for clearing up the problem :slight_smile:

Do you by any chance know if there is some way (maybe some tool) to test how a movie will run under different processors or something like that?
'cause if I do decide on using an onEnterFrame and hittest, I would like to know what machine would be needed to run the movie with acceptable framerate.

Thanks again.

I’m sorry, I don’t :frowning:

It’s time for me to go to sleep now, but I’ll think about it in the meanwhile.

Thanks a lot.

And if anybody in the meanwhile has some more suggestions: please feel free to join in :stuck_out_tongue:

this “no nested buttons” problem can be quite a pain. there’s a property, trackAsMenu, that seems like it’s designed precisely for this circumstance, but it appears to have no effect. if anyone knows what that property actually does, i’d be happy to know!

one approach is to make a main button such that it won’t obscure the sub buttons (ie, the subs are not in the main). have it trigger the menu open, then run an onEnterFrame that checks to see if the mouse is over any of the sub buttons or the main button. if it isn’t, close the menu and cancel the onEnterFrame.

i’ve amended your code to work that way and attached it. i used the background images as main buttons. you’ll have to make them clips in your fla and name them ‘mainbg’ for this code to work.

the changes are (only changed lines are shown):


		// make the text field non-selectable, that allows the bg
		// to receive mouse events
		_root["item"+i]["itemField"+i].selectable = 0;

		// curSub needs to register that the mouse is out
			curSubItem.onRollOut = function(){
				this.over = 0;
			}

		// woo hoo, this one's way different!  this replaces the onRollOver
		// that previously went on _root["item"+i].  it looks to see if the
		// mouse is over the menu or not, and closes the menu if it isn't
		_root["item"+i].mainbg.onRollOver = function(){
			this.over = 1;
			this._parent.menuDown();
			this._parent.FadeIn();
			this.onEnterFrame = function(){
				if(this.over) return false;
				var i;
				for(i in this._parent){
					if(this._parent*.over) return false;
				}
				this.onEnterFrame = null;
				this._parent.menuUp();
				this._parent.FadeOut();
			};
		}

		// very different again.  replaces _root["item"+i] again.  it records
		// a mouseout.  don't retract the menu here because that's
		// happening in the above function.
		_root["item"+i].mainbg.onRollOut = function(){
			this.over = 0;
		}

// you'll want to put more goodies in here no doubt,
// don't delete the over = 1 though.
MovieClip.prototype.subHighLight = function(){
	//this.attachMovie("buttonMC", "buttonMC_highlight", 100);
//	trace("test");
	this.over = 1;
};

there’s probably other small changes that i’ve forgotten, refer to the file to be sure.

just one approach, but it’s worked for me.

cheers.

That’s great. Thanks for the detailed explanation. :love:

I’ve got one more question if you don’t mind:

How would I make the textfield inside the subItem mc change its format to bold for instance?

I tried assigning the createTextField line to a variable:
[AS]
curSubField = curSubItem.createTextField(“subItemField_”+i+""+j, myDepth, 0, 0, root[“item”+i].width, spacing);
curSubItem["subItemField
"+i+"
"+j].text = curSubItemName;
curSubItem["subItemField
"+i+"_"+j].setTextFormat(myFormat);

curSubItem.onRollOver = function(){
this.subHighLight();
curSubField.setTextFormat(activeFormat);
}
[/AS]
However, that doesn’t seem to work.

Then I wondered if I could access the textfield inside the subItem mc as an array:
[AS]
curSubItem.onRollOver = function(){
this.subHighLight();
this[TextField[0]].setTextFormat(activeFormat);
}
[/AS]
Again, not working :frowning:

How would I go about doing this?

Thanks.

since currSubItem is unique each time you’re creating a text field, there’s no reason not to statically name them all ‘text’ (or something). there will be no name collisions because they’re all in different movie clips. for the same reason, you don’t need to use ‘i’ in naming curSubItem, just ‘j’ will do.

assigning from createTextField doesn’t work. oversight on macromedia’s part if you ask me. assign a text field to a variable after creating it, like so:

myClip.createTextField(‘text’,0,0,0,0,0);
var tf = myClip.text;

once you’re naming the text field the same way each time, referencing it becomes trivial. say you named it ‘text’:


curSubItem.onRollOver = function(){
        this.subHighLight();
        this.text.setTextFormat(activeFormat);
}

although for sake of keeping code where it should be (highly subjective :wink: ) i’d put the setTextFormat in subHighLight() and change the event assignment to:


curSubItem.onRollOver = subHighLight;

i can’t help noticing that the TextFormat ‘activeFormat’ appears to be a local variable that’s never defined. you might consider putting things like Text Format objects all in one place and referencing them when you need them. that way you only have one of them in memory. as long as you name them carefully, you can even get away with putting them in _root.

looking for the Text Field as an array was good thinking but AS doesn’t work that way. that’s a DOM technique, no?

cheers.

Thanks, I learned some new things today =)

And before reading your post I indeed came to the conclusion that I didn’t have to give each subItem’s textfield a unique name, so I changed the createTextField line to:
[AS]
curSubItem.createTextField(“subItemField”, myDepth, 0, 0, _root[“item”+i]._width, spacing);
[/AS]
and then:
[AS]
curSubItem.onRollOver = function(){
this.subHighLight();
this.subItemField.setTextFormat(activeFormat);
}
[/AS]
that did the trick :slight_smile:

to me it’s a bit strange that for createTextField, assigning directly to a variable doesn’t work while for e.g. createEmptyMovieClip it does… confusing :-/

the textFormat ‘activeFormat’ I indeed declared earlier in the script, just didn’t post it. my bad.

and accessing the TextField as being part of an array was just a shot in the dark I must say. It just sounded logic to me, but unfortunately it wasn’t…

Anyways, all is working now so I’m happy. Thanks again for all the explanations :thumb: