JavaScript Weshalb funktioniert dieser Snippet nicht in einer Funktion, aber dafür einzeln als onclick-Funktion?

_anonymous0815_

Lt. Commander
Registriert
Aug. 2020
Beiträge
1.307
###DISCLAIMER###
Das ist für mich mein erstes Webprojekt, andere Sprachen sind mir geläufiger als js und php, deshalb wird dieses Projekt ein Kopf-durch-die-Wand-Projekt, vor allem weil mir aktuell die Zeit fehlt, mich in diese Sprachen einzulesen.
###############

Guten Abend,

Hier habe ich schon mal das Projekt geschildert.

AKtuell plagt mich ein neues Problem, das beinhaltet folgenden Code:

Javascript:
function login() {
    username = document.getElementById('linuxuser').value;
    password = document.getElementById('password').value;

    console.log(username, password); // Bis hier wird alles richtig ausgefuehrt

    var message = JSON.stringify({
      type: 'input',
      data: username + '\n'
    });
    iframe.contentWindow.postMessage(message, url);

    message = JSON.stringify({
      type: 'input',
      data: password + '\n'
    });
    iframe.contentWindow.postMessage(message, url);
  };

Wenn ich jetzt einem input Element mit dem Type "button" eine Funktion mit dem "onclick"-Event hinzufüge, funktioniert noch der erste Teil des Codes und ich bekomme username und password ausgegeben. Der zweite Teil will nicht, als ich den zweiten Teil in eine eigene Funktion gepackt habe und die Variablen durch feste Werte ersetze, funktioniert auch der Teil, allerdings können über diesem Wege definitiv auch Variablen übergeben werden, siehe hier.

Was mache ich hier falsch?

Für Ratschläge bin ich sehr dankbar!
Ergänzung ()

PS, auch die Variable message wird richtig ausgegeben.
 
Was sagt den die Browser Konsole, normalerweise steht da in rot wenn und warum etwas nicht geht.

Was mir hier auffällt wenn ich das lese.

Du rufst hier innerhalb der Funktion die variable iframe auf.
Diese ist aber nirgendwo definiert. Daher mit dem Code den ich hier sehe, kann das nicht funktionieren.
 
iframe, sowie username und password sind außerhalb initialisiert. So wie ich es beim lesen verstanden habe, wird damit eine Variable erzeugt, welche auch innerhalb der Funktion verwendet werden kann. Liege ich damit falsch?
 
Logge die Variable halt raus, wenn du dir nicht sicher bist. Aber gebe dir recht.
 
kim88 schrieb:
Was sagt den die Browser Konsole, normalerweise steht da in rot wenn und warum etwas nicht geht.
Da steht leider gar nichts, lediglich die Ausgabe zu username und password.
Ergänzung ()

Ich habe jetzt auch mal iframe in den Log geschrieben und die Variable ist richtig "gefüllt", daran allein kann es nicht liegen.
 
_anonymous0815_ schrieb:
iframe, sowie username und password sind außerhalb initialisiert. So wie ich es beim lesen verstanden habe, wird damit eine Variable erzeugt, welche auch innerhalb der Funktion verwendet werden kann. Liege ich damit falsch?

Nein damit liegst du richtig. Wollte nur sichergehen, dass die Variabeln deklariert sind. Ich nehme an "url" ist ebenfalls ausserhalb deklariert.

Du kannst versuchen die PostMessage Funkton zu debuggen:

Dazu öffnest du im Browser die Seite wo das iFrame eingebunden wird. Öffnest wieder die Konsole und gibst dort folgendes ein:
Javascript:
window.addEventListener('message', console.log)

Das bestätigst du mit der Eingabe Taste. Es wird eine kleine "undefined" Warnung kommen die du ignorieren kannst.

Dann löst du den Event aus, der das PostMessage auslösen soll. Dann solltest du entweder ein Object mit deiner PostMessage wie im Screenshot sehen oder eine Fehlermeldung.

Bildschirm­foto 2023-01-06 um 19.13.40.png
 
kim88 schrieb:
Nein damit liegst du richtig. Wollte nur sichergehen, dass die Variabeln deklariert sind. Ich nehme an "url" ist ebenfalls ausserhalb deklariert.
Genau, deshalb schriebst du auch:
"Du rufst hier innerhalb der Funktion die variable iframe auf.
Diese ist aber nirgendwo definiert. Daher mit dem Code den ich hier sehe, kann das nicht funktionieren."

kim88 schrieb:
Du kannst versuchen die PostMessage Funkton zu debuggen:
Ja, könnte er.

kim88 schrieb:
Dazu öffnest du im Browser die Seite wo das iFrame eingebunden wird. Öffnest wieder die Konsole und gibst dort folgendes ein:
Javascript:
window.addEventListener('message', console.log)

Das bestätigst du mit der Eingabe Taste. Es wird eine kleine "undefined" Warnung kommen die du ignorieren kannst.
gemacht

kim88 schrieb:
Dann löst du den Event aus, der das PostMessage auslösen soll. Dann solltest du entweder ein Object mit deiner PostMessage wie im Screenshot sehen oder eine Fehlermeldung.

Anhang anzeigen 1308009
Hat bei mir nicht funktioniert.

Kann es sein, dass du die Richtung verwechselst?
Im Beispiel sendet der IFrame an das Parent, aber ich dachte es soll andersrum sein?
 
kim88 schrieb:
Dazu öffnest du im Browser die Seite wo das iFrame eingebunden wird. Öffnest wieder die Konsole und gibst dort folgendes ein:
Da kommt nur die "undefined"-Meldung, ansonsten nichts. :/
Ergänzung ()

kim88 schrieb:
Nein damit liegst du richtig. Wollte nur sichergehen, dass die Variabeln deklariert sind. Ich nehme an "url" ist ebenfalls ausserhalb deklariert.
URL ist außerhalb definiert und auch richtig initialisiert: PHP-Variable $_SERVER speichert in ip und url ruft http://{ip}:4200` auf. Das wird korrekt an die Server-IP aufgelöst.

PS: Ja, http, ist zum debuggen einfacher und ich weiß imemr noch nicht, ob ich am Ende https implementieren kann.
 
UPDATE:

Javascript:
var message;
var username, password;

document.getElementById("start").addEventListener("click", async function() {

  message = JSON.stringify({
        type : 'reconnect'
    });
  iframe.contentWindow.postMessage(message, url);

  await sleep(250);

  username = document.getElementById('linuxuser').value;
  password = document.getElementById('password').value;
 
  console.log(username, password);
 
  login(username, password);

});

function login (u, p) {
  message = JSON.stringify({
    type: 'input',
    data: u + '\n'
  });
  iframe.contentWindow.postMessage(message, url);
 
  message = JSON.stringify({
    type: 'input',
    data: p + '\n'
  });
  iframe.contentWindow.postMessage(message, url);
};

So funktionierts.
 
Blöde Frage, aber was ist nun konkret anders?
Und das mit der globalen Variable message finde ich extrem unschön...
 
statt onclick=function() nehme ich jetzt den eventListener() mit dem Event "click". Anscheinend kann das Backend von Shell in a box damit besser umgehen.

Die globale Variable message brauche ich, weil ich sie nicht in jeder Funktion neu initialisieren möchte, im Grunde ist sie jedoch überflüssig, möglicherweise fliegt sie beim säubern raus.
 
Was heißt denn "neu initialisieren"? Eine lokale Variable ist weniger dramatisch als eine globale, die eigentlich gar nicht gebraucht wird...

Und das heißt der Grund, warum es nicht ging, war gar nicht Teil des Snippets. Schön. Da können wir ja lange schauen.
 
  • Gefällt mir
Reaktionen: kim88
tollertyp schrieb:
Und das heißt der Grund, warum es nicht ging, war gar nicht Teil des Snippets. Schön. Da können wir ja lange schauen.
_anonymous0815_ schrieb:
Wenn ich jetzt einem input Element mit dem Type "button" eine Funktion mit dem "onclick"-Event hinzufüge
Bitte genau lesen, danke.
Ergänzung ()

tollertyp schrieb:
Was heißt denn "neu initialisieren"? Eine lokale Variable ist weniger dramatisch als eine globale, die eigentlich gar nicht gebraucht wird...
Irgendwann muss sie initialisiert werden. Mache ich das innerhalb einer Funktion, kann ich das in jeder Funktion machen. + Definition. Ich mache das nur hobbymäßig, aber mir erscheint es auf diese Weise effizienter, aber wie gesagt, sie kann auch ganz raus und ich ändere es auf diese Weise ab:

Javascript:
iframe.contentWindow.postMessage(JSON.stringify({
            type : "input",
            data : "ls -l\n"
        }), "https://192.168.1.150:4200");

So ist es hier vermerkt.
 
Das heißt aber auch, dass sie von jeder Funktion geändert werden kann wenn sie nicht scoped ist. Scoping hat schon seine guten Gründe.
Außerdem ist es generell bad practice das window object mit globals vars zu polluten.
 
  • Gefällt mir
Reaktionen: aronlad
Es gibt da die tolle Erfindung namens Parameter (einer Funktion).

Klar kann man
Code:
username = document.getElementById('linuxuser').value;
machen, aber was wenn man die Funktion irgendwo anders wieder verwenden will (der Grundzweck einer Funktion)?
 
_anonymous0815_ schrieb:
Bitte genau lesen, danke.
  • Nicht Teil des Snippets
  • Und was macht das?
Code:
document.getElementById("start").addEventListener("click", async function() {
Etwa nicht das:
Wenn ich jetzt einem input Element mit dem Type "button" eine Funktion mit dem "onclick"-Event hinzufüge

Aber ist klar, der Leser ist schuld.
Ergänzung ()

Zum Thema Stil:

Man könnte
Code:
JSON.stringify({
    type : "input",
    data : "ls -l\n"
});
auch in eine function auslagern, die lediglich noch den Inhalt für data erhält. Und auch das postMessage ist extrem redundant... und schwupps braucht es gar keine Variable message mehr... gut, jetzt könnte man sie auch nicht rausloggen, aber selbst wenn man das wollte, wäre es nur noch eine lokale Variable an genau einer Stelle, und die ist einer globalen Variable immer zu bevorzugen.

Code:
function login(u, p) {
  postInput(u);
  postInput(p);
}

function postInput(inputData) {
  iframe.contentWindow.postMessage(createInputMessage(inputData), url);
}

function createInputMessage(inputData) {
  return JSON.stringify({
    type: 'input',
    data: inputData+ '\n'
  });
}
(ungetestet, geht um das "Konzept")

Und auch wenn es ein Hobby-Projekt ist, sollte man schon ein wenig auf Stil wert legen. Zumal es Gründe hat, einen "vernünftigen" Stil zu nehmen, denn es ist nicht mehr Aufwand, sondern am Ende weniger Aufwand, wenn der Code lesbarer und wartbarer ist.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: aronlad und _anonymous0815_
Zurück
Oben