2017-07-23 2 views
-1

Je rencontre des problèmes de portée et de fermeture dans un extrait de code JavaScript. J'essaye de mettre à jour les propriétés class et onclick d'un bouton. Fondamentalement, cela devrait basculer entre "High" et "Low". Je pourrais obtenir la fonction pour exécuter sans essayer de redéfinir les paramètres, mais il n'a pas réussi à mettre à jour les propriétés. Donc, j'ai essayé de le redéfinir au code ci-dessous et j'obtiens maintenant une erreur que channel n'est pas définie. Quelqu'un peut-il m'aider avec la syntaxe ici? J'ai besoin de la fonction interne pour pouvoir évaluer à la fois le canal et la valeur.Syntaxe et délimitation de la syntaxe JavaScript

Je sais que le code fourni ne fonctionnera pas en raison du rappel asynchrone. Je ne peux pas sembler obtenir la syntaxe de portée correcte pour la fonction onreadystatechange. S'il vous plaît laissez-moi savoir si je peux fournir plus de clarification pour le problème que j'ai. Merci.

function setDio(channel, value) { 
 
    var xmlhttp = new XMLHttpRequest(); 
 
    xmlhttp.onreadystatechange = (function(channel,value) { return function(){ 
 
     if (this.readyState === 4) 
 
\t \t { 
 
\t \t \t if (this.status === 200) { 
 
\t \t \t \t document.getElementById('ok-msg').innerHTML = 'Digital Output successfully set to '+value+'.'; 
 
\t \t \t \t document.getElementById('ok-alert').style.display = 'block'; 
 
\t \t \t \t if(value===1) 
 
\t \t \t \t { 
 
\t \t \t \t \t document.getElementById('dio'+channel+'-high').class = 'ibradioactive'; 
 
\t \t \t \t \t document.getElementById('dio'+channel+'-low').class = 'ibradioinactive'; 
 
\t \t \t \t \t document.getElementById('dio'+channel+'-low').onclick = function(){ setDio(channel,0);};; 
 
\t \t \t \t \t document.getElementById('dio'+channel+'-high').onclick = function(){} ;; 
 
\t \t \t \t } 
 
\t \t \t \t else 
 
\t \t \t \t { 
 
\t \t \t \t \t document.getElementById('dio'+channel+'-high').class = 'ibradioinactive'; 
 
\t \t \t \t \t document.getElementById('dio'+channel+'-low').class = 'ibradioactive'; 
 
\t \t \t \t \t document.getElementById('dio'+channel+'-high').onclick = function(){ setDio(channel,1);};; 
 
\t \t \t \t \t document.getElementById('dio'+channel+'-low').onclick = function(){} ;; 
 
\t \t \t \t } 
 
\t \t \t } 
 
\t \t \t else 
 
\t \t \t { 
 
\t \t \t \t document.getElementById('error-msg').innerHTML = 'Digital Output set failed ('+ this.status +'): '+this.responseText; 
 
\t \t \t \t document.getElementById('error-alert').style.display = 'block'; 
 
\t \t \t } 
 
     } 
 
    };})(channel,value); 
 
    xmlhttp.open('POST', '/dio/' + channel, true); 
 
    xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 
 
    xmlhttp.send('dio-value=' + value); 
 
}
.alert,.ok-alert,.error-alert,.info-alert,.warning-alert { 
 
font-family:arial; 
 
font-weight:700; 
 
color:#FFF; 
 
margin-bottom:15px; 
 
border-radius:20px; 
 
padding:20px; 
 
display:none; 
 
} 
 

 
.ok-alert { 
 
background-color:#4CAF50; 
 
} 
 

 
.error-alert { 
 
background-color:#f44336; 
 
} 
 

 
.info-alert { 
 
background-color:#2196F3; 
 
} 
 

 
.warning-alert { 
 
background-color:#ff9800; 
 
} 
 

 
.alert-close { 
 
margin-left:15px; 
 
color:#FFF; 
 
font-weight:700; 
 
float:right; 
 
font-size:22px; 
 
line-height:20px; 
 
cursor:pointer; 
 
transition:.3s; 
 
} 
 

 
.inner-group { 
 
display:inline-block; 
 
border:0 solid #000; 
 
font-family:arial; 
 
font-weight:700; 
 
font-size:12pt; 
 
background:#ccc; 
 
border-radius:15px; 
 
vertical-align:text-top; 
 
box-shadow:4px 4px 10px #66a; 
 
margin:10px; 
 
padding:10px 4px; 
 
transition:1s; 
 
} 
 
.ibradioactive { 
 
background:#11AF11; 
 
} 
 

 
.ibradioactive span { 
 
color:#fff; 
 
} 
 

 
.ibradioinactive span { 
 
color:#000; 
 
} 
 

 
.ibradioinactive { 
 
background:#ddd; 
 
} 
 

 
.ibradioinactive:hover { 
 
background-color:#acf; 
 
} 
 

 
.ibradio,.ibradioactive,.ibradioinactive { 
 
width:50px; 
 
height:50px; 
 
cursor:pointer; 
 
box-shadow:3px 3px 2px #000; 
 
-webkit-box-shadow:3px 3px 2px #000; 
 
-moz-box-shadow:3px 3px 2px #000; 
 
font-weight:700; 
 
color:#000; 
 
border-radius:40px; 
 
border:1px solid #999; 
 
margin:10px 10px 10px 20px; 
 
padding:5px; 
 
} 
 
label { 
 
display:inline-block; 
 
width:125px; 
 
padding:3px 10px; 
 
}
<div id="error-alert" class="error-alert"> 
 
    <span class="alert-close" onclick="this.parentElement.style.display='none';">&times;</span> 
 
    <span id="error-msg">This is an error alert box.</span> 
 
</div> 
 
<div id="ok-alert" class="ok-alert"> 
 
    <span class="alert-close" onclick="this.parentElement.style.display='none';">&times;</span> 
 
    <span id="ok-msg">This is a success alert box.</span> 
 
</div> 
 
<div id="info-alert" class="info-alert"> 
 
    <span class="alert-close" onclick="this.parentElement.style.display='none';">&times;</span> 
 
    <span id="info-msg">This is an info alert box.</span> 
 
</div> 
 
<div id="warning-alert" class="warning-alert"> 
 
    <span class="alert-close" onclick="this.parentElement.style.display='none';">&times;</span> 
 
    <span id="warning-msg">This is an warning alert box.</span> 
 
</div> 
 
<br /> 
 

 
<div class="inner-group" style="width:550px;"> 
 
<label class="l2">Digital I/O #1</label><br> 
 
<label class="l2" style="width:175px">Mode: OUTPUT</label><br /> 
 
<label class="l2">New State:</label> 
 
<button class ="ibradioactive" type="submit" id="dio1-high" name="dio1-high" onclick="setDio(1,1)"><span>HIGH</span></button> 
 
<button class ="ibradioinactive" type="submit" id="dio1-low" name="dio1-low" onclick="setDio(1,0)"><span>LOW</span></button> 
 
</div>

EDIT:

Voici une version simplifiée de mon code original qui ne fonctionnait pas:

function setDio(channel, value) { 
 
    var xmlhttp = new XMLHttpRequest(); 
 
    xmlhttp.onreadystatechange = function() { 
 
    if (this.readyState === 4) 
 
    { 
 
     if (this.status === 200) { 
 
     if(value === 1) 
 
     { 
 
      document.getElementById('dio'+channel+'-high').class = 'ibradioactive'; 
 
      document.getElementById('dio'+channel+'-low').class = 'ibradioinactive'; 
 
     } 
 
     else 
 
     { 
 
      document.getElementById('dio'+channel+'-high').class = 'ibradioinactive'; 
 
      document.getElementById('dio'+channel+'-low').class = 'ibradioactive'; 
 
     } 
 
     } 
 
    } 
 
    }; 
 
    xmlhttp.open('POST', '/dio/' + channel, true); 
 
    xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 
 
    xmlhttp.send('dio-value=' + value); 
 
}

Comme cela ne fonctionnait pas, j'ai essayé de re-scoping et d'ajouter une fermeture pour m'assurer que la fonction évaluait les valeurs de paramètres qui étaient utilisées au moment de l'appel par rapport à la récupération des valeurs par défaut.

Les classes ne changeaient pas comme prévu et, en fait, la requête asynchrone n'était pas réellement détectée par le serveur. Donc, quelqu'un peut-il voir pourquoi cette fonction particulière ne fonctionnerait pas correctement? J'ai des fonctions similaires qui ne font que mettre à jour des valeurs simples innerHTML avec succès. Changer la classe, cependant, ne semble pas fonctionner.

EDIT 2:

Alors, j'ai découvert une partie de mon problème. La raison pour laquelle la classe ne changeait pas est que j'essayais de définir le class avec du texte au lieu d'un objet. Passer à className semble avoir éclairci cela. Je suis également retourné à ne pas utiliser de portée de fermeture supplémentaire et cela peut fonctionner correctement maintenant. Toujours en train de tester pour vérifier tous les changements.

+1

S'il vous plaît faire bouillir votre code pour quelques lignes douzaine. –

+1

Je deuxième commentaire de torazaburo. HTML et CSS semblent inutiles et si votre problème concerne les étendues, l'appel 'document.getElementById()' n'est pas non plus nécessaire. Les observations de valeurs provenant du débogueur ou des sorties de la console devraient suffire. Veuillez ajouter une description de résultat _expected_ et _actual_. Et s'il vous plaît réduire l'indentation. –

+0

Vous ne savez pas pourquoi l'extrait de code a mis de telles indentations. Je pense qu'il a été converti en onglets pour une raison quelconque. J'ai inclus tout parce que la fonction devrait changer les propriétés de style CSS et elles ne sont pas changées. Je vais simplifier mon code pour inclure simplement le JS pertinent à regarder. Pas tout à fait pourquoi vous avez dit 'getElementById()' n'est pas nécessaire. Sinon, comment vais-je accéder aux propriétés des éléments qui doivent être modifiés lorsque les résultats de la requête ont été renvoyés? – Psyfun

Répondre

2

Je ne sais pas pourquoi il est nécessaire de fermeture explicite défini ..

xmlhttp.onreadystatechange = function() { 
    console.log(channel); // parent function parameter can still be accessed here. 
} 
+0

Bien que vous ayez raison, il s'agit plutôt d'un commentaire et comme il est actuellement écrit, la question est assez floue car il manque une description claire du problème. Envisagez de mettre à jour votre question avec _references (de MDN par exemple) added_ et mettez-le à jour en fonction des clarifications de question plus tard. –

+0

Donc, à l'origine, je pensais que c'était aussi vrai, mais les choses ne se comportaient pas correctement. Les bonnes valeurs ne sont pas accessibles ou modifiées. Je vais mettre à jour ma question avec un avant et après les changements de code. – Psyfun

+0

Pour en revenir à aucune portée ou fermeture supplémentaire semble effectivement fonctionner. J'ai peut-être résolu le problème avec la modification de l'attribut de classe. Merci pour les suggestions et l'aide. – Psyfun