Javascript: input-Element nachträglich einbinden - oninput und onblur funzen nicht
- dom
- javascript
Moin,
für unseren Chorverband mache ich eine Webseite, in der Chöre ihre Setliste (Lieder beim Auftritt) eingeben können, als PDF speichern und der GEMA senden.
Der Gag: Mehr als 1000 Titel in der DB, die beim Tippen vorgeschlagen werden mit Komponist usw.
Etwa 15 Titel passen auf eine Seite. Wenn die nicht ausreichen, können leere Positionen ergänzt werden.

Die baue ich per Javascript ein.
// 3. input-Element definieren
let input_1 = document.createElement("input");
if ( i==1 )
input_1.required = "required";
input_1.id = "titel_" +i;
input_1.type = "text";
input_1.classList = "rest bold";
input_1.name = "titel[" +i +"]";
input_1.title = 'titel_required varchar(50)';
input_1.size = 70;
input_1.style = "position:relative;max-width:100%";
input_1.maxlength = 70;
input_1._alue = '[titel]';
input_1.placeholder = "Titel " +i;
input_1.autocomplete= "off";
input_1.oninput = "getLieder( this )";
input_1.onblur = "getLiederSchliessen()";
Klappt soweit bis auf oninput und onblur, die sind im Code nicht zu sehen, also keine Verbindung zur DB.
Wie handelt man diese beiden „Eigenschaften“?
Gruß, Linuchs
Moin Linuchs,
Die baue ich per Javascript ein.
// 3. input-Element definieren let input_1 = document.createElement("input"); if ( i==1 ) input_1.required = "required"; input_1.id = "titel_" +i; input_1.type = "text"; input_1.classList = "rest bold"; input_1.name = "titel[" +i +"]"; input_1.title = 'titel_required varchar(50)'; input_1.size = 70; input_1.style = "position:relative;max-width:100%"; input_1.maxlength = 70; input_1._alue = '[titel]'; input_1.placeholder = "Titel " +i; input_1.autocomplete= "off"; input_1.oninput = "getLieder( this )"; input_1.onblur = "getLiederSchliessen()";Klappt soweit bis auf oninput und onblur, die sind im Code nicht zu sehen, also keine Verbindung zur DB.
Wie handelt man diese beiden „Eigenschaften“?
Davon ausgehend, dass es „globale Funktionen” (auf window) sind (was dir vermutlich von anderen Kritik einbringen wird, aber sei's drum), kannst du eine Eigenschaft von Funktionen nutzen:
Function.prototype.toString() liefert dir einen String mit der Implementierung zurück. (Ausnahme sind dabei vom Browser bereitgestellte Funktionen. Da siehst du den Funktionskörper nicht).
Schau hier, dass auch die richtigen Werte in der Funktion ankommen. Unter Umständen hilft hierbei auch ein gut gesetztes bind().
Gruß,
Hallo,
du solltest zunächst verstehen, was die Unterschiede zwischen Methoden, Attributen und EVents für ein HTML-Element sind und wie man diese definiert.
input und blur sind Events und entsprechend musst du diese definieren via EventListener, was beim event gemacht werden soll. Also so:
const blurFunction = function(event){
console.log("blur event was triggered")
};
// eventFunction definieren
input_1.addEventListener("blur", blurFunction);
Und als Zusatzinfo, du solltest einen Debouncer einbauen. D.h. wenn Text eingegeben wird, sollte nicht sofort die Anfrage an die Datanbank gehen, sondern zeitverzögert, wenn nicht mehr getippt wird. Ansonsten ist es schlecht für die Performance. Debouncing Lösungen gibt es viele. Hier ein paar Lösungsansätze: Debouncing für Suchanfragen
Gruss
Hallo Linuchs,
Gunnar hat Dir bestimmt schon sieben Mal gesagt, dass Placeholder kein Ersatz für Labels sind. Ich sage es Dir hiermit zum achten Mal.
Klappt soweit bis auf oninput und onblur, die sind im Code nicht zu sehen, also keine Verbindung zur DB.
Könntest Du dieses Problem vielleicht mit mehr und klareren Worten beschreiben? Für mich ist dieser Satz unverständliches Kauderwelsch. Wieso ist es für die Verbindung zur DB relevant, ob die oninput und onblur-Eigenschaften im Code zu sehen sind? Wobei ich auch nicht verstehe, warum sie nicht zu sehen sein sollten.
Jedes input-Element hat die oninput und onblur-Eigenschaft. Darin findest Du die Funktion, die der Browser Dir aus dem String generiert hat, den Du im oninput- bzw. onblur-Attribut notiert hast. Willst Du den Attributinhalt, dann verwende bspw. den Methodenaufruf inputElem.getAttribute("oninput"). Aber ich wüsste nicht, wofür das von Bedeutung wäre.
Das input-Element selbst übergibst Du ja eh als Parameter an getLieder, und das ist das eigentlich wichtige im Eventhandling. Ich hoffe, du legst um die input-Elemente einer Titelgruppe zumindest ein div. Damit fällt die Navigation zu den Nachbarinputs deutlich leichter.
Dass es sinnvoller ist, Eventhandling mit addEventListener zu betreiben, und dass ein Debouncer für die Suche sinnoll ist, kann ich nur unterschreiben. Zu beiden Themen findest Du einiges im Selfwiki.
Grundsätzlich würde ich die Eventlistener aber auch nicht auf den inputs direkt definieren, sondern auf einem gemeinsamen Elternelement und dann das Bubbling nutzen. Mal angenommen, das HTML sähe so aus (du hast doch eine Liste für die Titelliste verwendet, oder?)
<ol class="titelListe">
<li>
<div>
<label for="titel_1">Titel</titel>
<input type="text" id="titel_1" name="titel_1" required ...>
</div>
<div>
<label for="komponist_1">Komponist</titel>
<input type="text" id="komponist_1" name="komponist_1" ...>
</div>
<div>
<label>Bearbeiter</titel>
<input type="text" id="bearbeiter_1" name="bearbeiter_1" ...>
</div>
</li>
...
</ol>
Praktisch wird es anders aussehen, wegen der vergrößerten Indexnummern. Stylen kannst Du das jedenfalls alles ausgehend von .titelListe.
Die Eventhandler für input und blur definiere dann auf dem ol Element!!!
const titelListe = document.querySelector(".titelListe");
titelListe.addEventListener("input", getLieder);
titelListe.addEventListener("blur", getLiederSchliessen);
function getLieder(inputEvent) {
const eingabe = inputEvent.target; // Das input-Element, das das Event gefeuert hat
const eintrag = eingabe.closest("li"); // Das li-Element dieser Eingabegruppe
const titel = eintrag.querySelector("input[name^=titel]");
const kompo = eintrag.querySelector("input[name^=kompo]");
const bearb = eintrag.querySelector("input[name^=bearb]");
// Jetzt hast Du alle 3 Felder im Zugriff
if (eingabe == titel) { // Es wurde etwas im Titel eingegeben
... suchen
titel.value=suchErgebnis.titel;
kompo.value=suchErgebnis.komponist;
bearb.value=suchErgebnis.bearbeiter;
}
}
function getLiederSchließen(blurEvent) {
}
Ich kann den richtigen Code jetzt natürlich nur andeuten, bei Dir ist das in Callbacks vom Ajax-Aufruf verpackt. Aber ich hoffe, ich konnte Dir die Idee zeigen.
Für einen neuen Eintrag baust Du Dir das innerHTML für das neue li Element als String zusammen. Und zwar in einer Funktion, damit Du prima mit einem Template-String arbeiten kannst, um die Indexnummer überall einzusetzen wo sie gebraucht wird. Welche das ist, musst Du natürlich erstmal rausfinden - aber das hast Du ja eh schon drin.
titelListe.append(createNewItem(index));
function createNewItem(index) {
item = document.createElement("li");
item.innerHTML =
`<div>
<label for="titel_${index}">Titel</titel>
<input type="text" id="titel_${index}" name="titel_${index}" required ...>
</div>
<div>
<label for="komponist_${index}">Komponist</titel>
<input type="text" id="komponist_${index}" name="komponist_${index}" ...>
</div>
<div>
<label for="bearbeiter_${index}">Bearbeiter</titel>
<input type="text" id="bearbeiter_${index}" name="bearbeiter_${index}" ...>
</div>`;
return item;
}
Im Detail wird das bei Dir natürlich anders aussehen.
Rolf
Lieber Linuchs,
input_1.autocomplete= "off"; input_1.oninput = "getLieder( this )"; input_1.onblur = "getLiederSchliessen()";
Du verwendest uralte JavaScript-Mechanismen, von denen Du besser die Finger lassen solltest, weil sie damals mangels besserer Alternativen eine Notlösung waren.
Du notierst mit input_1.onirgendwas = "ein String" im Grunde den Textinhalt eines HTML-Attributs gleichen Namens (hier onirgendwas). Was Du hier stattdessen tun solltest, ist einen passenden EventListener zu notieren:
input_1.addEventListener("irgendwas", function (event) {
// hier passiert etwas wenn das Event "irgendwas" feuert
});
// das gleiche mit einer Pfeilfunktion für input-Events
input_1.addEventListener("input", event => {
// event ist vom Typ "input"
});
// wenn Du eine Funktion öfters benötigst
function meineBlurFunktion (node) {
// node ist eine Referenz auf ein <input> element
}
// die anonyme Funktion (zweiter Parameter nach "blur")
// enthält eine gekapselte Variable "input_1" (Closure):
input_1.addEventListener("blur", function () {
meineBlurFunktion(input_1);
});
Bitte lasse künftig ab von diesen veralteten onirgendwas-Attributen/-Eigenschaften! Du machst Dir das Leben damit nicht leichter, weil Du nicht sicher sagen kannst, warum etwas (nicht) funktioniert.
→ unser Wiki zu Eventhandler-Funktionen und wie man sie an Elemente bindet
Liebe Grüße
Felix Riesterer
@@Felix Riesterer
Du notierst mit
input_1.onirgendwas = "ein String"im Grunde den Textinhalt eines HTML-Attributs gleichen Namens (hier onirgendwas). Was Du hier stattdessen tun solltest, ist einen passenden EventListener zu notieren:
Das gehört in jedes Stylesheet: 😏
[onclick], [onfocus], [onblur], [oninput], [onchange], [onsubmit], [onerror] {
outline: medium solid orange !important;
--WARNING: 'use `addEventListener()` instead of `on*` attribute';
}
(Möglicherweise habe ich noch das ein oder andere [on…] vergessen.)
🖖 Live long and prosper
@@Gunnar Bittersmann
Das gehört in jedes Stylesheet: 😏
[onclick], [onfocus], [onblur], [oninput], [onchange], [onsubmit], [onerror] { outline: medium solid orange !important; --WARNING: 'use `addEventListener()` instead of `on*` attribute'; }(Möglicherweise habe ich noch das ein oder andere
[on…]vergessen.)
Möglicherweise. Eben aber noch in @Linuchs’ Code gesehen, dass ich noch was anderes vegessen habe:
[placeholder] {
outline: medium solid orange !important;
--WARNING: 'don’t use placeholder';
}
🖖 Live long and prosper
Lieber Gunnar,
(Möglicherweise habe ich noch das ein oder andere
[on…]vergessen.)
gibt es dafür keine Wildcard-Schreibweisen wie es ja schon bei den Attributwerten [class^="on"] möglich ist?
Liebe Grüße
Felix Riesterer
@@Felix Riesterer
(Möglicherweise habe ich noch das ein oder andere
[on…]vergessen.)gibt es dafür keine Wildcard-Schreibweisen wie es ja schon bei den Attributwerten
[class^="on"]möglich ist?
War auch mein erster Gedanke. Der zweite dann: Moment mal, gibt’s das überhaupt? AFAIK gibt’s das nur für Attributwerte, nicht für Attributbezeichner.
🖖 Live long and prosper
Lieber Gunnar,
AFAIK gibt’s das nur für Attributwerte, nicht für Attributbezeichner.
eine ganz klare Lücke im Konzept! Wer ist schuld? Wen muss man da anpampen? Wann wird das endlich besser? Wenn ich doch nur Geduld hätte...
Liebe Grüße
Felix Riesterer
Moin Felix,
AFAIK gibt’s das nur für Attributwerte, nicht für Attributbezeichner.
eine ganz klare Lücke im Konzept! Wer ist schuld? Wen muss man da anpampen?
TC39.
Gruß,
@@Ryuno-Ki
AFAIK gibt’s das nur für Attributwerte, nicht für Attributbezeichner.
eine ganz klare Lücke im Konzept! Wer ist schuld? Wen muss man da anpampen?
TC39.
Und was genau hat ECMAScript mit einem CSS-Feature zu tun?
🖖 Live long and prosper
Moin Gunnar,
@@Ryuno-Ki
AFAIK gibt’s das nur für Attributwerte, nicht für Attributbezeichner.
eine ganz klare Lücke im Konzept! Wer ist schuld? Wen muss man da anpampen?
TC39.
Und was genau hat ECMAScript mit einem CSS-Feature zu tun?
Nicht mein Tag heute.
CSS WG gibt es auch auf GitHub.
Gruß,
@@Ryuno-Ki
Nicht mein Tag heute.
Das dachte ich mir schon. Damit bist du genug gestraft. Ich habe davon abgesehen, dich noch zusätzlich mit einem Minus zu strafen. 😉
CSS WG gibt es auch auf GitHub.
Ja, aber ich denke, @Felix Riesterer kann die Aussichten auf Realisierung realistisch einschätzen. HTML-Attribute sind nicht so benannt, als dass sie sich mit Stringanfang oder -ende sinnvoll gruppieren ließen. Die on…-Dinger wären da die Ausnahme.
In erster Linie aber ließ Felix’ Posting schon durch die Wahl der Sprache erkennen, dass es nicht so ganz ernst gemeint war.
Ich verfasse solche Postings auch desöfteren – ohne sie durch Smileys zu kennzeichnen (und damit den Charme etwas zunichtezumachen); jüngstes Beispiel. Ich baue da auf die Urteilskraft der Leser, aber es findet sich immer mal jemand, der keinen Spaß versteht.
🖖 Live long and prosper
Moin Gunnar,
Ich baue da auf die Urteilskraft der Leser, aber es findet sich immer mal jemand, der keinen Spaß versteht.
Jein. Neurodiversität ist ein weites Feld.
Damit auch ein anderes Thema, was hier nicht reinpasst.
Gruß,
Hallo Felix Riesterer,
// die anonyme Funktion (zweiter Parameter nach "blur")
// enthält eine gekapselte Variable "input_1" (Closure):
input_1.addEventListener("blur", function () {
meineBlurFunktion(input_1);
});
Besser nicht. Jedenfalls nur unter der Voraussetzung, dass input_1 als const deklariert ist.
Closures sind besser als globale Variablen, aber man sollte trotzdem nach Möglichkeit vermeiden, aus einer Funktion heraus auf Daten des Elternkontexts zuzugreifen. Ich würde die target-Eigenschaft des event-Objekts zu bevorzugen. Entweder gleich bei Übergabe an meineBlurFunktion, oder man schreibt explizit einen blur-Handler und vermeidet damit die Mediator-Funktion. Ein blur-Handler lässt sich auch wieder deregistrieren (was Linuchs ebenfalls nicht zu benötigen scheint).
// So
input_1.addEventListener("blur", function (blurEvent) {
meineBlurFunktion(blurEvent.target);
});
// Oder so
input_1.addEventListener("blur", handleBlurOnInput);
function handleBlurOnInput(blurEvent) {
...
}
Wobei Linuchs – sofern ich das richtig verstand – der Blur-Funktion gar keine Daten mitgibt, sondern lediglich das Auswahlfenster schließt.
Und wenn ich nochmal darauf hinweisen darf: gerade wenn man Forms dynamisch erweitert, ist es in den meisten Fällen hilfreich, die Eventhandler ein einzigs Mal auf dem Form zu registrieren und die Events dahin blubbern zu lassen, statt on the fly einen Eventhandler nach dem anderen ins DOM zu kleben.
Rolf