steve: Undefined Object

Hallo miteinander

Wäre froh wenn ihr mir mal ein Auge leihen könntet: Es geht um folgendes Script, welches das Menü einer Page steuert. Zuerst werden inaktive Submenüs onload() ausgeblendet, dann entsprechend den Aktionen des Users wieder ein- und ausgeblendet.
Das Ganze funktioniert grundsätzlich, allerdings hab ich noch Probleme mit undefinierten Objekten in der FIFO Warteschlange, die mir dann je nach Systemeinstellungen das ganze Design verreissen. Auf jeden Fall seh ich - wie das manchmal so ist bei eigenem Code - einfach den/die Fehler nicht.
Ich bin bestimmt kein Javascript Ass, komme von C/C++/C#/PHP/Java her und wär ziemlich froh wenn mir mal wer auf die Sprünge helfen würde..

Also ich poste einfach mal den gesamten Code (die initializer-Scripts funktionieren aber soweit):

var Navigation = (function (){ // controls a navigation  
		var nav = {};  
		  
		var TheOpen = -1;  
		var TheActive;  
		var ToOpen = -1;  
		var FirstLevelNodes;  
		var ShadowDiv;  
		  
		var FuncFIFO;  
		var TheFade=-1;  
		  
		var Timer;  
		var MaxMenuOpenTime=2000; //ms  
		var MouseOverMenu=false;  
		var FuncProcessing=false;  
		  
		function timerCheck()  
		{  
			Time=new Date();  
			if( ( Time.getTime()-Timer ) > MaxMenuOpenTime && Timer!=0 && !MouseOverMenu && !FuncProcessing )  
			{  
				if( TheOpen==TheActive )  
				{  
					Timer=0;  
					return;  
				}  
				  
				if(TheOpen!=-1)sfadeOut(TheOpen);  
				ffadeIn(TheActive);  
				Timer=0;  
			}  
		};  
		  
		function funcStart(_func,_period,_elementPointer,_functionId)  
		{  
				var element=new Array();  
				element[0]=_func;  
				element[1]=_period;  
				element[2]=_elementPointer;  
				element[3]=_functionId;  
				FuncFIFO.push(element);  
				FuncProcessing=true;  
				  
				if( FuncFIFO.length == 1 )  
				{  
					_func(_elementPointer);  
					TheFade=window.setInterval( function(){ _func(_elementPointer); },_period );  
				}  
		};  
		  
		function funcStop()  
		{  
				window.clearInterval(TheFade);  
				FuncFIFO.shift();  
				  
				if( FuncFIFO.length>=1 )  
				{  
					FuncFIFO[0][0]( FuncFIFO[0][2] );  
					TheFade=window.setInterval( function(){ FuncFIFO[0][0]( FuncFIFO[0][2] ); },FuncFIFO[0][1] );  
				}  
				else if( FuncFIFO.length==0 ) FuncProcessing=false;  
		};  
		  
		function ffadeIn(_what)  
		{  
				funcStart(fadeIn,10,_what,0);  
		};  
		  
		function sfadeIn(_what)  
		{  
				funcStart(fadeIn,50,_what,0);  
		};  
		  
		function ffadeOut(_what)  
		{  
				funcStart(fadeOut,10,_what,1);  
		};  
		  
		function sfadeOut(_what)  
		{  
				funcStart(fadeOut,50,_what,1);  
		};  
		  
		function fadeIn(_what)  
		{  
			var object;  
			open(_what);  
			TheOpen=_what;  
			  
			if( _what==-1 )  
			{  
				funcStop();  
				return;  
			}  
			  
			for(var i=0;i<_what.parentNode.childNodes.length;i++)  
			{  
				if( _what.parentNode.childNodes[i].nodeName=="UL" ) object=_what.parentNode.childNodes[i];  
			}  
			  
			var Handle=object;  
			var opacity=Number(Handle.style.opacity);  
			  
			if( opacity==1||opacity==0 ) opacity=Number(0);  
			  
			opacity=Number(opacity)+0.08;  
			  
			if( opacity>=1 ){ //overflow  
				opacity=1.0;  
				funcStop();  
			}  
			  
			ShadowDiv.style.opacity=opacity;  
			Handle.style.opacity=opacity;  
		};  
		  
		function fadeOut(_what)  
		{  
			var object;  
			TheOpen=-1;  
			if( _what==-1 )  
			{  
				funcStop();  
				return;  
			}  
			  
			for(var i=0;i<_what.parentNode.childNodes.length;i++)  
			{  
				if( _what.parentNode.childNodes[i].nodeName=="UL" ) object=_what.parentNode.childNodes[i];  
			}  
			  
			var Handle=object;  
			var opacity=Handle.style.opacity;  
			  
			if( opacity==0 ) opacity=1;  
			  
			opacity=opacity-0.08;  
			  
			if( opacity<=0.01 ){ //overflow  
				close(_what);  
				TheOpen=-1;  
				/*if(ToOpen!=-1)  
				{  
					open(ToOpen);  
					TheOpen=ToOpen;  
				}*/  
				opacity=1.0;  
				ShadowDiv.style.opacity=opacity;  
				Handle.style.opacity=opacity;  
				funcStop();  
				//if(ToOpen!=-1) ffadeIn();  
			}  
			else{  
				ShadowDiv.style.opacity=opacity;  
				Handle.style.opacity=opacity;  
			}  
			return;  
		};  
		  
		function getOpenElement()  
		{  
			var actualOpen;  
			  
			if( FuncFIFO.length!=0 )  
			{  
				if( FuncFIFO[FuncFIFO.length][3]==0 ) actualOpen=FuncFIFO[FuncFIFO.length][2];  
				else actualOpen=-1;  
			}  
			else actualOpen=TheOpen;  
			  
			return actualOpen;  
		};  
		  
		nav.mouseovermenu = function()  
		{  
			MouseOverMenu=true;  
		}  
		  
		nav.mouseoutofmenu = function()  
		{  
			MouseOverMenu=false;  
			Time=new Date();  
			Timer=Time.getTime();  
		}  
		  
		nav.initialize = function()  
		{  
			Timer=0;  
			FuncFIFO=new Array();  
			MainMenu=document.getElementById("main_nav");  
			FirstLevelNodes = MainMenu.childNodes;  
			MainMenu.onmouseover=function(){ nav.mouseovermenu(); return; };  
			MainMenu.onmouseout=function(){ nav.mouseoutofmenu(); return; };  
			makeSiteReady();  
			window.setInterval(timerCheck,1000);  
			  
			StartLink=document.getElementById("nav_el_0");  
			for( var i=0;i<StartLink.childNodes.length;i++)  
			{  
				if(StartLink.childNodes[i].nodeName=="A")  
				{  
					StartLink=StartLink.childNodes[i];  
					break;  
				}  
			}  
			StartLink.onmouseover="";  
		}  
  
		nav.click = function(_This)  
		{  
			var actualOpen=getOpenElement();  
			  
			if(_This==actualOpen) return;  
			  
			if( actualOpen!=-1 ) ffadeOut(actualOpen);  
			  
			ffadeIn(_This);  
			return;  
		};  
		  
		nav.expandedClick = function(_This)  
		{  
			var ContainedLink;  
			for( var b=0; b<_This.childNodes.length; b++ )  
			{  
				if( _This.childNodes[b].nodeName=="A" )  
				{  
					ContainedLink=_This.childNodes[b].href;  
				}  
			}  
			window.open(ContainedLink,"_self");  
		};  
		  
		function makeSiteReady() //closes sub menues and adds onclick events to their parent nodes  
		{  
		  
			document.body.className="jsEnabled";  
			var NumberOfFLN = FirstLevelNodes.length;  
			TheActive=-1;  
			var CountFake=0;  
			  
			for(var i = 0;i<NumberOfFLN;i++){ //iterate through all li elements of main_nav: FirstLevelNodes[i]: a "li" element  
				if(FirstLevelNodes[i].childNodes.length>1 ){ //if li has more than one child  
					if( isActive(FirstLevelNodes[i]) )  
					{  
						open( FirstLevelNodes[i].childNodes[1] );//opens the active submenu  
						TheOpen=FirstLevelNodes[i].childNodes[1];  
						TheActive=FirstLevelNodes[i].childNodes[1];  
					}  
					  
					expandLinkArea( FirstLevelNodes[i] );  
					FirstLevelNodes[i].childNodes[0].onmouseover=function(){  
						nav.click( this );return;  
					};  
					  
					  
					if( CountFake==0 )  
					{  
						  
						var fakeDiv = document.createElement("div");  
						fakeDiv.id="shadowdiv";  
						ShadowDiv=fakeDiv;  
						FirstLevelNodes[i].appendChild(fakeDiv);  
						CountFake++;  
					}  
					  
					FirstLevelNodes[i].style.background="none";  
							  
					  
				}  
				if( FirstLevelNodes[i].childNodes.length==1 )  
				{  
						FirstLevelNodes[i].childNodes[0].onmouseover=function(){  
							nav.click( -1 );return;  
						};  
				}  
			}  
			return;  
		};  
		  
		function isActive( _This ) //checks whether the element is one that has been marked as being active - and sets it as the clicked/open  
		{  
				if( _This.className.search(/active/)==-1 )return false;  
				//TheOpen=_This.childNodes[0];  
				return true;  
		}  
		  
		function close( _This )  
		{  
			if( _This==-1 ) return;  
			for(var i=0;i<_This.parentNode.childNodes.length;i++)  
			{  
				if( _This.parentNode.childNodes[i].nodeName=="UL" )_This.parentNode.childNodes[i].className="";  
			}  
		};  
		  
		function open( _This )  
		{  
			if( _This==-1 ) return;  
			for(var i=0;i<_This.parentNode.childNodes.length;i++)  
			{  
				if( _This.parentNode.childNodes[i].nodeName=="UL" )_This.parentNode.childNodes[i].className="open";  
			}  
		};  
		  
		function expandLinkArea( _target ) // expands the link area of links contained in a li element to the whole li  
		{  
			var Children=_target.childNodes;  
			for( var i=0; i<Children.length; i++ )  
			{  
				if( Children[i].nodeName=="UL" )  
				{  
					var GrandChildren=Children[i].childNodes;  
					for( var a=0; a<GrandChildren.length ; a ++ )  
					{  
						if( GrandChildren[a].nodeName=="LI" )  
						{  
							  
							GrandChildren[a].onclick=function(){  
								nav.expandedClick( this ); return;  
							};  
						}  
					}  
				}  
			}  
		};  
		  
		  
		return nav;  
})();  
  
  
function afterLoad(){  
		  
		Navigation.initialize();  
}

Merci!!

  1. Hallo,

    Das Ganze funktioniert grundsätzlich, allerdings hab ich noch Probleme mit undefinierten Objekten in der FIFO Warteschlange

    Für den Anfang könntest du den Code bei jshint.com reinpasten, was dir evtl. Syntaxprobleme, globale Variablen, ungünstige Vergleiche usw. anzeigt.
    Z.B. ist die Variable Time global, was wohl nicht sein muss.

    Mit Firebug für Mozilla Firefox kann mann gut debuggen, z.B. Haltepunkte setzen und schrittweise die Werte aller Variablen verfolgen. Das sollte helfen rauszufinden, was wann wo und warum unerwartet undefined ist.

    Da JavaScript zur Laufzeit kompiliert wird, macht der Compiler keine Optimierungen. Dafür muss man selber sorgen, z.B. folgendes

    open( FirstLevelNodes[i].childNodes[1] );//opens the active submenu  
    TheOpen=FirstLevelNodes[i].childNodes[1];  
    TheActive=FirstLevelNodes[i].childNodes[1];  
    
    ~~~``{:.language-javascript}  
      
    besser so notieren:  
      
    ~~~javascript
    var firstNode = FirstLevelNodes[i].childNodes[1];  
    open( firstNode );//opens the active submenu  
    TheOpen = TheActive = firstNode;
    

    Es ist übrigens in JS üblich, dass man normale Variablennamen mit Kleinbuchstaben beginnt und nur Konstruktornamen (mit new aufzurufen) mit Großbuchstaben.

    Merci!!

    gärn gschäh,

    Don P

    1. Merci für den Tipp mit jshint.com - hat mir ein par Unsauberkeiten aufgezeigt und mit den Breakpoints von Chrome (die hat der auch) hab ich auch den Fehler gefunden! Merci!