Hey
also ich habe jetzt einige Änderungen vorgenommen und mein Event wird immer überschrieben, es übergibt nur einen Wert an setAutoComplete. Nämlich den letzten aus der Iteration.
Und das wundert dich? ;-)
$.each(msg, function (i, value) {
Zunächst mal wäre zu erwähnen, dass es zwar grundsätzlich sinnvoll ist, wenn man schon ein Framework wie jQuery einbindet, sich auch dessen Methoden zu bedienen, aber von jeder Regel gibt es Ausnahmen.
Hier die generische Methode each
des jQuery-Objektes zu verwenden ist nicht falsch, aber auch nicht wirklich sinnvoll. Zumindest, sofern es sich bei dem Wert von msg
um ein iterierbares Objekt handelt, also zum Beispiel um ein gewöhnliches Array.
Sollte dies der Fall sein, wäre die native Methode forEach
vorzuziehen, welche direkt auf jeder Arrayinstanz aufgerufen werden kann.
msg.forEach(function (value, index /* array */) {
// do something
});
Beachte, dass hier die Reihenfolge der Argumente, mit denen die Callback-Funktion aufgerufen wird anders herum ist als bei der Methode each
, also erst der aktuelle Wert und dann der Index.
Als drittes Argument wird darüber hinaus noch eine Referenz auf das Array übergeben, über welches iteriert wird. Aber die brauchst du hier nicht, also kann man sich die Deklaration eines dritten Parameters in diesem Fall sparen.
item = value.split(";");
An dieser Stelle liegt die Ursache für das von dir beschriebene Problem.
button.addEventListener('click', function () { setAutoComplete(item[0], item[1], parent, idField) });
Was glaubst du passiert, wenn diese Funktion aufgerufen wird?
In diesem Fall wird versucht, die Referenz mit dem Bezeichner item
aufzulösen, was innerhalb dieser Funktion nicht möglich ist, da weder ein Parameter noch eine lokale Variable mit diesem Bezeichner deklariert wurde.
Da du in der äußeren lexikalischen Umgebung der Handlerfunktion, also der an each
übergebenen Rückruffunktion, wie gesehen ebenfalls keine Variable mit dem Bezeichner item
deklariert hast, sondern lediglich eine Variable in einem umgebenden Gültigkeitsbereich referenzierst, wird entsprechend dort weitergesucht.
Schließlich wird von jeder Handlerfunktion, die du innerhalb der an each
übergebenen Callback-Funktion definierst, ein und dieselbe Variable referenziert, und da die Eventhandler erst ausgeführt werden, wenn die Iteration abgeschlossen ist, wird entsprechend der Wert zurückgegeben, welcher der Variable item
zuletzt zugewiesen wurde.
var item = value.split(';');
Was du also eigentlich möchtest, ist bei jedem Aufruf der an each
übergebenen Funktion eine lokale Variable anzulegen, sodass der Wert in der Closure, also dem Funktionsabschluss konserviert wird.
try{ //.. } catch(e) { alert("Fehler: " + e.message); }
Ich würde mich für einen Klammerstil entscheiden. Es fördert nicht unbedingt die Lesbarkeit des Codes, wenn man das mal so und mal so macht. Davon abgesehen scheint mir try
und catch
an dieser Stelle ziemlich überflüssig.
Hier kann eigentlich nur dann ein Fehler auftreten, wenn in der Variable div
kein Objekt ist, dass die Methode appendChild
implementiert, und hier prüfst du immerhin gegen null
und undefined
.
Sollte das Statement und der Aufruf von alert
dem Debugging dienen, dann möchte ich noch hinzufügen, dass dies nicht der richtige Ansatz ist. Hierfür solltest du die Entwicklerwerkzeuge deines Browsers verwenden. Dort werden dir in der Konsole Fehler angezeigt, üblicherweise mit Typ, Message, Stacktrace, Script und Zeilennummer.
Über die console
API stehen dir verschiedene Methoden zur Verfügung, um Kontrollausgaben in der Konsole des Browsers zu machen. Unter anderem log
für einfache Kontrollausgaben, dir
für Inspektionen, warn
für Warnungen, error
für eigene Fehlermeldungen, info
für zusätzliche Informationen und assert
für Fehlermeldungen, wenn eine bestimmte Annahme nicht zutrifft.
const foo = null;
console.assert(foo === 'bar', 'foo is not bar');
Das ergibt einen Fehler, Assertion failed. Darüber hinaus kannst du im Script mit dem debugger
-Statement auch Breakpoints setzen, an denen dein Programm angehalten werden soll. Dann kannst du die verschiedenen Variablen und die Werte die zu einem bestimmten Zeitpunkt mit ihnen verknüpft sind im Debugger des Browsers inspizieren.
var div = document.getElementById('targetUI'); if (div != null) { div.appendChild(li);
Das hatte ich in meiner anderen Antwort ja schon angesprochen. Es ist extrem verwirrend, wenn du eine Variable div
nennst, die eigentlich eine ul
referenziert. Das ist nicht nachvollziehbar und sollte geändert werden. Davon abgesehen verwendest du jQuery, also kannst du dir den Aufruf der Methode getElementById
hier sparen und einfach $('#targetUI')
schreiben.
const $targetUI = $('#targetUI');
if ($targetUI.length) {
Wenn es kein Element mit der ID targetUI
gibt, wird von jQuery ein leeres Objekt zurückgegeben. Du kannst also wie in dem Beispiel oben auf die Existenz prüfen. Ich habe hier dem Namen der Konstante das Prefix $
vorangestellt, um zu verdeutlichen, dass hier ein jQuery-Objekt und nicht direkt ein Element referenziert wird, aber das kannst du natürlich halten wie du willst.
//create new listelement for station and mark as selected var li = document.createElement('li'); li.type = 'li'; li.className = 'selected'; //create button in listelement for station var button = document.createElement('button'); button.type = 'button'; button.textContent = item[1]; button.id = item[0]; if (i == 0) { button.className = 'dropdownelement'; } //add button to listelement li.appendChild(button);
Auch hierfür wären entsprechende jQuery-Methoden zu verwenden, wenn du dieses Framework schon einbindest. Allerdings ist nicht alles was du hier tust sinnvoll.
li.type = 'li';
Das ergibt zum Beispiel keinen Sinn, denn li
hat kein type
-Attribut.
Darüber hinaus solltest du beachten, dass die Vergabe einer Klasse selected
nicht dazu führt, dass Benutzer assistiver Software über den Zustand deines Widgets in Kenntnis gesetzt werden. Hier wirst also noch etwas Arbeit investieren müssen, wenn das Ganze zugänglich sein soll.
Viele Grüße,
Orlok