2016-11-27 1 views
0

Kann mir jemand sagen, was ich falsch mache? Ich habe einen ganzen Tag mit der Fehlerbehebung verbracht, aber ich komme nirgendwohin ... Ich möchte das Ereignis "onmouseover" zu meinen span-Elementen hinzufügen. Wenn ich jedoch den folgenden Code implementiere, passiert nichts. Ich habe ein wenig gegoogelt und ich denke, dass es ein Problem mit einem variablen Bereich sein könnte. Ich bin nicht zu sicher ... Jede Hilfe ist willkommen!Probleme beim Hinzufügen eines Ereignisses "onmouseover" zu einer Spanne

<!DOCTYPE html> 
<html> 
    <head> 
     <title>Fixing bugs in JS</title> 
     <script src="question1.js" type="text/javascript"></script> 
    <head> 
    <body> 
     <div id="output"></div> 
    </body> 
<html> 

var NUMBERS = 100; 

function go() 
{ 
    var out = document.getElementById("output"); 
    for (var i = 1; i < NUMBERS+1; i++) { 
    var span_one = document.createElement("span"); 
     span_one.id = "span" + i; 
     span_one.innerHTML = "" + i; 
     out.appendChild(span_one); 

    if (isPrime(i) === true) { // where i is a prime number (3, 5, 7..etc) 
     span_one.style.backgroundColor = "red"; 
     span_one.onmouseover = function() { 
     hover("span"+i, "yellow", "150%") 
     }; 
     span_one.onmouseout = function() { 
     hover("span"+i, "red", "100%") // whatever color in this line always overrides previous set color... 
     }; 
} 

function hover(id, color, size) { 
    var span = document.getElementById(id); 
    span.style.backgroundColor = color; 
    span.style.fontSize = size; 
} 


function etc() { 
    ... 
} 

window.onload=go; 

+0

Das Problem, das ist, wenn sie aufgerufen, 'I' nicht mehr hält, was es zu halten braucht. (Der Wert von i innerhalb von onmouseover ist nicht das gleiche wie wenn es als Parameter zu isPrime verwendet wurde) – enhzflep

+0

@enhzflep Ich überprüft über console.log (span_one.id) und es hält den Wert, den es annehmen soll ... – aeml

+0

Das ist nicht dasselbe. 'span_one.id' _should_ muss denselben Wert wie' i' haben, tut es aber nicht. – enhzflep

Antwort

0

Ihr Problem ist, dass Sie Schließungen um Ihre i Variable haben.

Verschlüsse treten auf, wenn Sie eine Funktion in einer anderen Funktion verschachteln. Der Code wird unvorhersehbar ausgeführt, wenn die verschachtelte Funktion eine Variable aus einer Vorgängerfunktion verwendet und die verschachtelte Funktion eine längere Lebensdauer als der betreffende Vorgänger hat.

hier Ihre mouseover und mouseout Funktionen stützen sich auf i von der übergeordneten Funktion go. Da die Funktionen mouseover und mouseout an DOM-Elemente angefügt werden und diese DOM-Elemente im Speicher verbleiben, bis die Seite entladen wird, haben diese Funktionen eine längere Lebensdauer als go. Das bedeutet, dass die i-Variable, die go deklariert ist, nicht aus dem Gültigkeitsbereich gehen kann, wenn go abgeschlossen ist und beide Mausfunktionen den gleichen Wert von i teilen. Der Wert, den i hat, wenn ein Mensch kommt und die Maus bewegt, ist der LETZTE Wert, den er hatte, als die Schleife endete.

Verschlüsse können auf den ersten Blick eine Herausforderung sein, aber Sie können ein wenig mehr über sie lesen here.

var i zu let i auf Schleife Ändern löst, dass, weil let stellt Umfang Block für jede Iteration der Schleife.

Außerdem sah ich, dass Sie zwei schließende geschweifte Klammern fehlten, die Fehler verursachten. Ich habe meine eigene isPrime() Funktion hinzugefügt. Siehe Anmerkungen für Standorte:

window.onload=go; 
 

 
const NUMBERS = 100; 
 

 
function go(){ 
 

 
    
 
    var out = document.getElementById("output"); 
 
    
 
    // Using let instead of var avoids a closure by making sure 
 
    // that each looping number exists in the block scope of the 
 
    // loop and upon each iteration a new variable is created. 
 
    for (let i = 1; i < NUMBERS+1; i++) { 
 
    
 
    var span = document.createElement("span"); 
 
    span.id = "span" + i; 
 

 
    span.innerHTML = i + "<br>"; 
 
    out.appendChild(span); 
 

 
    if (isPrime(i)) { // where i is a prime number (2, 3, 5, 7..etc) 
 
     span.style.backgroundColor = "red"; 
 
     
 
     // If you use the i variable in nested functions, you will create a 
 
     // closure around it and both the mouseover and mouseout functions will 
 
     // share the last known value of i. Each function must get its own copy 
 
     // of i. 
 
     span.onmouseover = function() { 
 
      hover("span" + i, "yellow", "150%") 
 
     }; 
 
     
 
     span.onmouseout = function() { 
 
     // whatever color in this line always overrides previous set color... 
 
     hover("span" + i, "red", "100%") 
 
     }; 
 
     
 
    } // <-- Missing 
 
    } // <-- Missing 
 
    
 
} 
 
    
 
function isPrime(value) { 
 
    for(var i = 2; i < value; i++) { 
 
     if(value % i === 0) { 
 
      return false; 
 
     } 
 
    } 
 
    return value > 1; 
 
} 
 

 
function hover(id, color, size) { 
 
    var span = document.getElementById(id); 
 
    span.style.backgroundColor = color; 
 
    span.style.fontSize = size; 
 
    console.log(id, span); 
 
}
<div id="output"></div>

+0

Hallo @Scott Marcus, wie kann ich diese Nummern so brechen, dass jede ihre eigene Zeile hat? Wenn ich out.innerHTML + = "
";, es bricht den Code. Ich bekomme den Onmouseover-Effekt nicht mehr. – aeml

+0

@aeml Ich habe meine Antwort aktualisiert, um das zu tun. Du musst das nur ändern: 'span.textContent = i;' dazu: 'span.innerHTML = i +"
";' –

+0

Vielen Dank !!! – aeml

0

Hier ist ein funktionierendes Beispiel:

http://jsbin.com/zixeno/edit?js,console,output

Das Problem ist genau das, was enhzflep sagte. Eine Lösung besteht darin, die "addSpan" -Logik aus der for-Schleife und in eine Funktion zu verschieben.

var NUMBERS = 100; 

function go() { 
    var out = document.getElementById("output"); 
    for (var i = 1; i < NUMBERS+1; i++) { 
    addSpan(i); 
    } 

    function hover(id, color, size) { 
    var span = document.getElementById(id); 
    span.style.backgroundColor = color; 
    span.style.fontSize = size; 
    } 

    function addSpan(i) { 
    var span_one = document.createElement("span"); 
    span_one.id = "span" + i; 
    span_one.innerHTML = "" + i; 
    out.appendChild(span_one); 

    if (isPrime(i) === true) { 
     span_one.style.backgroundColor = "red"; 
     span_one.onmouseover = function() { 
     hover("span"+i, "yellow", "150%") 
     }; 
     span_one.onmouseout = function() { 
     hover("span"+i, "red", "100%"); 
     }; 
    } 
    } 
} 
0

Das Problem ist mit der Variablen i, seine ein häufiges Problem mit Verschlüssen. Weitere Informationen finden Sie unter MDN closures und gehen Sie zum Abschnitt Creating closures in loops: A common mistake. Um dieses Problem zu beheben, ändern Sie die var in for-Schleife zu let. Dies hilft Ihnen, den Umfang beizubehalten und somit das Problem zu beheben.

var NUMBERS = 100; 
 

 
function go() { 
 
    var out = document.getElementById("output"); 
 
    for (let i = 1; i < NUMBERS+1; i++) { 
 
     let span_one = document.createElement("span"); 
 
     span_one.id = "span" + i; 
 
     span_one.innerHTML = "" + i; 
 
     out.appendChild(span_one); 
 

 
    if (isPrime(i) === true) { // if a number is a prime then run this func 
 
     span_one.style.backgroundColor = "red"; 
 
     span_one.onmouseover = function() { 
 
     hover("span"+i, "yellow", "150%") 
 
     }; 
 
     span_one.onmouseout = function() { 
 
     hover("span"+i, "red", "100%") // whatever color in this line always overrides previous set color... 
 
     }; 
 
    } 
 
    
 
    function hover(id, color, size) { 
 
     var span = document.getElementById(id); 
 
     span.style.backgroundColor = color; 
 
     span.style.fontSize = size; 
 
    } 
 
    
 
    //Added my custom function as it was not provided 
 
    function isPrime(i){ 
 
     return i%2 != 0; 
 
    } 
 
    } 
 
} 
 

 
window.onload = go;
<div id="output"></div>

+0

Dein Ergebnis ist das reverse was das OP will. Primes sollte rot sein. –

1

Es gibt wirklich keine Notwendigkeit, (a) eine ID, um die Elemente zu geben (b) für etwas anderes als die Schleife sie der Schaffung der i-Zähler zu verwenden. Hier ist eine Alternative.

function newEl(tag){return document.createElement(tag)} 
 
function byId(id){return document.getElementById(id)} 
 

 
window.addEventListener('load', onDocLoaded, false); 
 

 
function onDocLoaded(evt) 
 
{ 
 
\t var i, n = 100; 
 
\t var outputContainer = byId('output'); 
 
\t 
 
\t for (i=1; i<=n; i++) 
 
\t { 
 
\t \t var span = newEl('span'); 
 
\t \t //span.id = 'span_' + i; 
 
\t \t span.textContent = i; 
 
\t \t outputContainer.appendChild(span); 
 
\t \t 
 
\t \t if (i%2 == 1) \t // \t isOdd 
 
\t \t { 
 
\t \t \t span.addEventListener('mouseover', onSpanMouseOver, false); 
 
\t \t \t span.addEventListener('mouseout', onSpanMouseOut, false); 
 
\t \t } 
 
\t } 
 
} 
 

 
function onSpanMouseOver(evt) 
 
{ 
 
\t this.style.backgroundColor = 'yellow'; 
 
\t this.style.fontSize = '150%'; 
 
} 
 
function onSpanMouseOut(evt) 
 
{ 
 
\t this.style.backgroundColor = 'red'; 
 
\t this.style.fontSize = '100%'; 
 
}
<div id='output'></div>

+0

Ihr Code hat keinen Farbcode. –

+0

@ScottMarcus - Unsinn. Die Demo funktioniert genau hier auf der Seite. Hast du es nicht vor dem Posten versucht? (Ich tat es) Ungerade Zahlen werden gelb, wenn sie schweben und werden rot, wenn die Maus sie verlässt. – enhzflep

+0

Primes sollte automatisch rot sein. Dann werden sie beim Überstreichen gelb und dann beim Auslösen rot. –

Verwandte Themen