webForumDet fria alternativet

Mouseover fungerar på en länk men ej på andra

3 svar · 579 visningar · startad av m_soderlund

m_soderlundMedlem sedan sep. 20026 425 inlägg
#1

Jag letar rätt på element programmatiskt m h a javascript och lägger på ett onmouseover-event.

Jag har följande HTML:

<div class="module">
    <h2><a href="#1">Module #1</a></h2>
    
    <div class="content">
        <ul>
            <li><a href="#">Lorem ipsum dolor</a></li>
            <li><a href="#">Lorem H&amp;H</a></li>
            <li><a href="#">Dolor consecutor amis</a></li>
        </ul>
    </div>
</div>

<div class="module">
    <h2><a href="#2">Module #2</a></h2>
    
    <div class="content">
        <ul>
            <li><a href="#">Lorem ipsum dolor</a></li>
            <li><a href="#">Lorem H&amp;H</a></li>
            <li><a href="#">Dolor consecutor amis</a></li>
        </ul>
    </div>
</div>

Med hjälp av detta javascript letar jag rätt på alla <div class="content"> och sedan länkarna:

window.onload = function()
{
    var elem = getElementsByClassName(document, "div", "content");
    
    if (elem.length>0)
    {   
        for(var i=0; i<elem.length; i++)
        {
            var e = elem[i]; // div with content class
            var myElem = e.parentNode.getElementsByTagName("a")[0]; // get anchor in h2 element
           
            if (e != null)
            {            
                if (i != 0) // hide divs with class="content" (except first one)
                {
                    e.style.display = 'none';
                }
                
                myElem.style.border = 'solid 1px #111';
                
                myElem.onmouseover = function()
                {
                    e.style.display = 'block';
                    elem[0].style.display = 'none';
                }                                
            }
        }
    }
}

Problemet är bara att onmouseover-eventet bara fungerar för sista <div class="content"> och aldrig på den/de tidigare.

Meningen med scriptet är att det vid hovring av en länk ska visa innehåll nedanför länken i dess container medan de andra containrarna (<div class="content">) ska döljas.

Det är alltså myElem som onmouseover ska fungera för. Jag har även lagt på en border på myElem och det fungerar som det ska.

All hjälp mottages tacksamt! :)

nitro2k01Medlem sedan aug. 20039 342 inlägg
#2

Det grundläggande felet du har gjort är ett andtagande om scopes. for-loopen har inget eget scope, utan för varje runda av for-loopen så skrivs din variabel e över i scopet för onload-funktionen, trots att du använder var. Detta beteende var nytt för mig också, och något jag såg under testningen nu.
Detta löste jag genom att lägga en var inom en inre funktion (function(){...})(); vilket skapar ett nytt scope för varje runda. Skillnaden här är att variabeln thisindex tilldelas under varje runda, så den lider inte av överskrivningsproblem. I samma funktion tilldelar jag även event-handlern. elem ligger i onload-funktionens scope och är statisk under alla for-rundor, och behöver därmed inte klonas individuellt till under-scopet.

Jag antar att du inte vill dölja den första diven, (elem[0].style.display = 'none';) utan den senast öppnade? Detta gör du bäst med en for-loop som går igenom elementen och jämför index.

Dessutom har du onödigt mycket kontrollkod. if (elem.length>0) är helt onödigt då loop-villkoret i<elem.length ändå inte låter loopen köra ens en första runda om elem.length==0.
En annan sak är if (e != null). Om inte din getElementsByClassName-funktion är extremt dålig ska den aldrig returnera null-element. På sin höjd kan det hända att du får odefinierade element av olika skumma anledningar (Generellt, inte specifikt för detta skript) Det du ska kontrollera då är if('undefined' != typeof array[index]){/* Saker är ok */}
Detta ska du göra direkt på array[index]. Kör du en sats som var element = array[index]; så kommer skriptet packa ihop redan där och du får ingen chans att inspektera element.
Dessutom kör du ju e.parentNode.getElementsByTagName("a")[0]; innan du kollar om e är null, vilket isf skulle få skriptet att ge upp redan där om e av någon anledning faktiskt var null!

Om du vill kan jag berätta mer om skillnaden mellan null och undefined.

Nåväl, här är min lösning:

window.onload = function()
{
    var elem = getElementsByClassName(document, "div", "content");

	for(var i=0; i<elem.length; i++)
	{
		var e = elem[i]; // div with content class

		var myElem = e.parentNode.getElementsByTagName("a")[0]; // get anchor in h2 element

		if (i != 0) // hide divs with class="content" (except first one)
		{
			e.style.display = 'none';
		}

		(function(){	// Inner scope
			var thisindex=i;
			myElem.onmouseover = function()
			{
				for (var i=0; i<elem.length; i++){
					if (i==thisindex)
						elem[i].style.display = 'block';
					else
						elem[i].style.display = 'none';
				}
			}
		})();			// End of inner scope
	}
}
m_soderlundMedlem sedan sep. 20026 425 inlägg
#3

Det här var ju nästan för bra för att vara sant. En fungerande lösning och dessutom en mycket god förklaring till lösningen.

Tackar så mycket! (y)

Berätta gärna också mer om skillnaden mellan null och undefined. :)

nitro2k01Medlem sedan aug. 20039 342 inlägg
#4

Om du försöker komma åt en variabel som inte är definierad, så får du tillbaka undefined. Men undefined i sig är inte ett värde, utan tillståndet att ett variabelnamn är odefinierat i det nuvarande scopet. Normalt kastas det ett fel direkt när du försöker komma åt en odefinierad variabel. alert(jagexisterarinte); kommer t ex att stoppa skriptet. Lite annorlunda är det vad gäller arrayer. Om du försöker plocka ut något med ett index som inte existerar, så kommer du att få tillbaka en referens till ett faktiskt undefined-objekt, som dock är lite speciellt och har typen undefined istället för object som andra objekt. Detta objekt kan kommas åt med kodordet undefined. Detta är inte något som sker bara för att undefined råkar vara odefinierat, utan det refererar faktiskt till ett speciellt objekt. return undefined; är dock aldrig att rekommendera.

alert([][0]===undefined);
Visar exempelvis true. Hängde du med?
En tom array: []
Ett icke-existerande index i denna array: [][0]
Identisk jämförelse: ===
Det speciella objektet: undefined
Det korrekta sättet att testa efter undefined är dock med:
if ('undefined' == typeof variabel){ /* Ajaj! */}
När man kollar typen så fungerar det även med helt odefinierade variabler.

null däremot, är ett mer vanligt objekt, i det att man utan problem kan, och ibland bör, tilldela dess värde till saker. null står för att en objektreferens inte pekar nånstans. Exempelvis returneras null från DOM-funktioner som document.getElementById() när inget finns att returnera.
Dock så kommer DOM-funktioner som returnerar en nod lista, exempelvis document.getElementsByTagName() fortfarande returnera en tom nodlista om inget hittas. Du behöver dock inte oroa dig för att en funktion som document.getElementsByTagName() ska slänga ett fel bara för att du tilldelar ett värde, typ var taggar=document.getElementsByTagName("konstigtagg"); utan det sker isf först när man börjar pilla på elementen utan att kolla upp saker. (T ex genom att anta att det finns ett 0'te element utan kolla om det verkligen gör det)

Detta är dock ganska mycket överkurs, men det kan vara bra att att veta när man ska vänta sig null och när man ska vänta sig undefined för att öht göra en vettig kontroll.

132 ms totalt · 3 externa anrop · v20260731065814-full.beb2e261
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
130 ms — hämta tråd, inlägg och bilagor (db)