Warum wird mein Posting #2 ignoriert?
Beiträge von Sempervivum
-
-
Zitat
ich bearbeite es und schneide die dritte Spalte raus, füge es bei meine Website ein und der durchsichtige Effekt ist weg und ich frage mich warum das so ist.
Das kann viele Gründe haben: Vielleicht unterstützt dein Bildbearbeitungsprogramm keine Transparenz. Welches Programm hast Du zum Herausschneiden benutzt? Hänge am besten mal das Bild vor und nach der Bearbeitung an,damit man das überprüfen kann.
BTW: Mit dem Link aus Posting #3 hast Du gerade ein etwas unglückliches Beispiel heraus gegriffen weil es float benutzt. Bei einem Mehrspaltenlayout orientiere dich besser hieran:
-
Schau mal ob Du die Lösung hier findest:
-
Das ist ja wirklich heftig und ich bin mir nicht sicher, ob es als PM möglich ist. Versuche es bei https://pastebin.com
-
Ohne in den Code eingestiegen zu sein fallen mir mehrere Möglichkeiten ein:
- Eine globale Variable beim Klick auf eine Antwort setzen und im Eventhandler abfragen. Ist sie gesetzt, dann den Klick ignorieren.
- Eine Klasse bei den Buttons setzen und im Eventhandler abfragen. Ist sie gesetzt, dann den Klick ignorieren.
- Das CSS pointer-events: none; für die Buttons setzen. Dann werden Mausklicks ignoriert.
Alles lässt sich problemlos rückgängig machen, wenn wieder eine Frage präsentiert wird.
-
Wenn es nicht zu umfangreich ist, dann poste das Skript, das Du gemacht hast. Ich erinnere mich an Code wo ein Eventlistener im Callback eines anderen registriert wurde. Dann werden es mit jedem Klick immer mehr und mehr. Kann natürlich auch etwas anderes sein.
Wenn nur die betr. Seite abstürzt, könnte man wahrscheinlich auch einen Neustart hinbekommen: Die Seite mit window.open öffnen und Lebenszeichen an die öffnende Seite senden lassen. Bleiben diese aus, kann man davon ausgehen, dass die Seite abgestürzt ist, sie schließen und neu öffnen.
-
Zitat
Nach einigen Stunden, manchmal nach einigen Tagen, stürzt die App ab. Ruft man die Seite im Browser neu auf, läuft alles wieder für einige Zeit.
Da frage ich mich, ob da vielleicht irgend wo ein Speicherleck vorhanden ist, wo immer mehr Speicher angefordert wird. Oder ein Stackoverflow, dass eine Funktion rekursiv aufgerufen wird. Poste doch mal dieses Javascript, wenn es nicht zu umfangreich ist.
Wie man einen Neustart hinkriegen kann, weiß ich auf Anhieb nicht. Müsste man wahrscheinlich auf Betriebssystemebene machen, den Prozess überwachen und den Browser neu starten, wenn er nicht mehr da ist.
Besser erst Mal versuchen, das Problem an der Wurzel zu lösen.
Edit: Was heißt "stürzt ab"? Nur das Tab, wo die Seite läuft oder der Browser insgesamt? Sind irgend welche Fehlermeldungen sichtbar?
-
Freut mich, dass es funktioniert. Mit ein wenig CSS kann man dem Benutzer auch gleich bei der Eingabe signalisieren, dass der Wert noch nicht stimmt:
-
Zitat
dass bei einer Fehleingabe des Users das Formular stehen bleibt
Versuche es mit der Formularvalidierung durch HTML5, wie in meinem Beitrag #2 empfohlen.
Ändere z. B. das Eingabefeld für die Email indem Du den Typ auf "email" änderst und das Attribut "required" hinzu fügst:
<input type="email" name="email" placeholder="" id="email" required>
-
Danke, das ist schon mal sehr aufschlussreich. Scheint das besagte Affenformular zu sein, nur dann verstehe ich deine ursprüngliche Frage nicht: Wenn der Benutzer die Fehlermeldung sieht, müsste er darüber auch wieder das Formular sehen und in der Lage sein, seine Eingabe(n) dort zu korrigieren? Oder verstehe ich den Code falsch?
-
Hallo MarkusBEO
die Frage kann man nicht beantworten, ohne das Umfeld zu kennen: Wie wird das Formular abgeschickt? Ist es ein sogenanntes Affenformular, d. h. die Seite ruft sich selber auf? Oder wird beim Abschicken eine andere Seite aufgerufen? Oder wird das Formular mit Ajax abgeschickt?
Auf jeden Fall kann man sagen, dass unter dem Gesichtspunkt der Benutzerfreundlichkeit eine clientseitige Validierung, zusätzlich zur serverseitigen, zu empfehlen ist. Dann bekommt der Benutzer seine Rückmeldungen schon vor dem Abschicken. Mit der HTML5-Formularvalidierung ist das ja heute ein Kinderspiel:
https://developer.mozilla.org/en-US/docs/Lea…dation_examples
-
Ich möchte an dieser Stelle drei Demos für die grundlegende Anwendung der fetch-API vorstellen. Diese ermöglicht es, Daten an den Server zu übertragen ohne die Seite durch das Abschicken eines Formulars neu zu laden. In meinen Augen ist sie einfacher und übersichtlicher als das ältere XMLHttpRequest und daher meine bevorzugte Methode. Die Demos beschränken sich jeweils auf den Kern der Sache. Erweiterte Funktionen, z. B. Validierung der Daten, müssen ggf. noch hinzu gefügt werden. Anstatt den Code im Text zu erklären, habe ich jeweils Kommentare eingefügt.
Demo 1: Formulardaten an den Server schicken
HTML
Alles anzeigen<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>Fetch-API: Send Form Data</title> </head> <body> <form id="the-form"> <input type="text" name="param1" value="some-param"> <input type="text" name="param2" value="some-other-param"> <input type="number" name="numparam" value="1.24"> <button type="submit">Abschicken</button> </form> <!-- In den folgenden Container wird die Antwort vom Server eingetragen: --> <span id="out"></span> <script> // Eventlistener für das Abschicken des Formulars registrieren: document.getElementById('the-form').addEventListener('click', event => { // Um zu verhindern, dass die Seite mit dem PHP-Skript, // direkt aufgerufen wird unterdrücken wir die Standard-Aktion: event.preventDefault(); // PHP-Skript testpost.php aufrufen: fetch('testpost.php', { method: 'post', // Die Daten des Formulars werden im body übertragen: body: new FormData(document.querySelector('form')) }).then(res => { // Die Antwort vom Server wird als Text ausgewertet: return res.text(); }).then(res => { // Antwort vom Server in der Console ausgeben: console.log(res); // ... und in HTML-Element eintragen: document.getElementById('out').innerHTML = res; }); }); </script> </body> </html>Demo 2: Daten ohne Formular an den Server schicken
Für die Übertragung von Daten ist ein Formular nicht erforderlich. Sie können in das FormData-Objekt direkt eingetragen werden:
HTML
Alles anzeigen<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>Fetch-API: Send POST Parameters</title> </head> <body> <!-- In den folgenden Container wird die Antwort vom Server eingetragen: --> <span id="out"></span> <script> // Neues FormData-Objekt erzeugen: const params = new FormData(); // ... und die Parameter, die übertragen werden sollen, eintragen: params.append('param1', 'some-param'); params.append('param2', 'some-other-param'); params.append('numparam', '1.24'); // Parameter mit der Methode POST an das Skript testpost.php schicken: fetch('testpost.php', { method: 'post', body: params }).then(res => { // Die Antwort vom Server wird als Text ausgewertet: return res.text(); }).then(res => { // Antwort vom Server in der Console ausgeben: console.log(res); // ... und in HTML-Element eintragen: document.getElementById('out').innerHTML = res; }); </script> </body> </html>Zum Testen der Demos verwende ich dieses kurze PHP-Skript:
testpost.php
PHP<?php ini_set('display_errors', '1'); error_reporting(E_ALL); // Alle POST-Parameter mit var_dump ausgeben: var_dump($_POST); // Jeden einzelnen POST-Parameter mit echo ausgeben: foreach ($_POST as $key => $value) { echo $key . ": " . $value . "<br>"; }Demo 3: Datei zum Server hochladen
HTML
Alles anzeigen<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>Fetch-API: Upload file</title> </head> <body> <!-- Eingabefeld für das Auswählen der Datei: --> <input type="file" id="file-input"> <!-- Button um das Hochladen nach dem Auswählen einer Datei zu starten: --> <button id="upload-btn">Upload</button> <!-- In den folgenden Container wird die Antwort vom Server eingetragen: --> <span id="out"></span> <script> const fileInput = document.querySelector('#file-input'), uploadBtn = document.querySelector('#upload-btn'); // Eventlistener für Klick auf den Upload-Buttton registrieren: uploadBtn.addEventListener('click', () => { // Neues FormData-Objekt erzeugen: const formData = new FormData(); // ... und die ausgewählte Datei dort eintragen: formData.append('file', fileInput.files[0]); // Datei zum Sever hochladen: fetch('upload.php', { method: 'POST', body: formData, }).then(response => { return response.text() }).then(text => { console.log(text); document.getElementById('out').innerHTML = text; }); }); </script> </body> </html>Zum Testen dieser Demo verwende ich dieses kurze PHP-Skript:
upload.php
PHP
Alles anzeigen<?php ini_set('display_errors', '1'); error_reporting(E_ALL); // In $_FILES stehen die Informationen über die hochgeladene Datei: var_dump($_FILES); // 'file' ist darin gleich dem Namen des Eingabefeldes, // mit dem die Datei zum Hochladen ausgewählt wurde: if ($_FILES['file']['error'] != 0) { echo 'Error: ' . $_FILES['file']['error'] . '<br>'; } else { echo 'Datei ' . $_FILES['file']['name'] . ' wurde erfolgreich hochgeladen<br>'; // Die Datei steht unter einem temporäten Namen zur Verfügung. // Wir übertragen sie in das gewünschte Verzeichnis. // Dabei kann ggf. auch ein geänderter Dateiname verwendet werden. move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $_FILES['file']['name']); }Auch hier müssen ggf. noch weitere Funktionen hinzu gefügt werden: Beschränkung des Typs, z. B. auf Bilddateien, Beschränkung der Dateigröße etc.
Hier muss auf eine Einschränkung der fetch-API hingewiesen werden: Sie unterstützt, anders als das ältere XMLHttpRequest, keine Fortschrittsanzeige.
-
Das ist eine Eigenart von Javascript in Verbindung mit HTML: Gibt man einem Element eine ID, so ist es automatisch auch als globale Variable mit der ID als Name definiert. Etwas wovon man besser keinen Gebrauch machen sollte. Die Probleme gehen los, wenn man z. B. Minuszeichen in der ID hat: Dann funktioniert das mit dem Variablennamen nicht aber man findet z. B. solch ein div <div id="test-global-var"></div> als window['test-global-var'] wieder.
-
Nein, ohne CSS geht das nicht. Was Du brauchst ist background-size, siehe z. B. hier:
https://developer.mozilla.org/de/docs/Web/CSS/background-size
Und allgemein zu CSS hier:
https://wiki.selfhtml.org/wiki/CSS/Tutor…heets_einbinden
Und BTW: Styling mit Attributen wie bgcolor und tags wie <center> ist, bis auf ganz wenige Ausnahmen, veraltet und sollte durch CSS ersetzt werden.
-
Zitat
mit der Berechnung im TimeOut funktioniert es, allerdings auf meinem Rechner erst ab 50 ms. 10 ms sind ihm zu wenig, dann ist die Berechnung falsch und der Wert noch zu gering. Bei diesem Vorgehen ist man also darauf angewiesen, dass der Server nicht allzu langsam antwortet.
Das verstehe ich jetzt nicht ganz, warum man auf die Antwort vom Server warten muss. Die Berechnung findet ja innerhalb des then-Zweiges für die Anfrage statt, d. h. dort sollte die Antwort vollständig vorliegen. Es sei denn, ich habe mich mit den Klammern irgend wie verguckt.
Aber ich erwarte, dass sich das Ganze auch mit CSS lösen lässt, siehe meine vorigen Postings. Dann würde sich das Problem erübrigen.
-
Man kann jedoch auch mit Gridlayout eine Überlappung erzeugen, siehe hier:
https://mastery.games/post/overlapping-grid-items/
Damit und mit Verschiebung durch transform: translate; sieht es dann so aus:
HTML
Alles anzeigen<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Test</title> <style> #grid-container { display: grid; /* Wenn wir das Overlay nach oben verschieben soll es unsichtbar sein: */ overflow: hidden; } #grid-container>div { /* Damit sich beide Container überlappen weisen wir sie der selben Zelle im Grid zu: */ grid-column: 1; grid-row: 1; } #playpart { background-color: lightblue; } #redOverlay { background-color: red; color: white; display: flex; align-items: center; justify-content: center; /* Dieser Container soll den umgebenden div#playpart vollständig ausfüllen. Beim Grid ist das automatisch erfüllt: */ /* height: 100%; width: 100%; */ /* Um ihn zunächst unsichtbar zu machen, verschieben wir ihn nach oben: */ transform: translateY(-100%); transition: transform 0.5s; } #redOverlay.visi { /* Overlay jetzt sichtbar machen: */ transform: translateY(0); } </style> </head> <body> <div id="grid-container"> <div id="redOverlay"> Falsch! </div> <div id="playpart"> Vestibulum vel metus. Donec sagittis velit vel augue. Fusce in nisl vitae massa venenatis rhoncus. Praesent orci velit, Gekürzt! </div> </div> <button id="the-button">Klick!</button> <script> document.getElementById('the-button').addEventListener('click', event => { document.getElementById('redOverlay').classList.add('visi'); }); </script> </body> </html> -
Hier die klassische Variante mit absoluter Positionierung, Javascript nur noch für den Eventlistener auf den Button:
HTML
Alles anzeigen<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Test</title> <style> #playpart { background-color: lightblue; position: relative; /* Wenn wir das Overlay nach oben verschieben soll es unsichtbar sein: */ overflow: hidden; } #redOverlay { background-color: red; color: white; display: flex; align-items: center; justify-content: center; /* Dieser Container soll den umgebenden div#playpart vollständig ausfüllen: */ height: 100%; width: 100%; position: absolute; top: 0; left: 0; /* Um ihn zunächst unsichtbar zu machen, verschieben wir ihn nach oben: */ top: -100%; transition: top 0.5s; } #redOverlay.visi { top: 0; } </style> </head> <body> <div id="playpart"> <div id="redOverlay"> Falsch! </div> Vestibulum vel metus. Donec sagittis velit vel augue. Fusce in nisl vitae massa venenatis rhoncus. Praesent orci velit, Gekürzt! </div> <button id="the-button">Klick!</button> <script> document.getElementById('the-button').addEventListener('click', event => { document.getElementById('redOverlay').classList.add('visi'); }); </script> </body> </html> -
Du hast Recht, ich hatte da zwei Dinge nicht bedacht:
1. Das HTML ist erst vollständig fertig nach der Schleife.
2. Das DOM einschl. der Abmessungen wird nicht sofort aktualisiert während das Javascript durchläuft. Man muss mit setTimeout einen kurzen Moment warten, dann sind die endgültigen Abmessungen verfügbar.
Code}); // Ende des inneren Ajax }); // Ende des Eventlisteners } Ende der Schleife setTimeout(function() { // hier die Abmessungen berechnen }, 10); }); // Ende des äußeren Ajax } // Ende der FunktionZitatNach Klick auf einen Button wird eine CSS-Transition hinzugefügt, die das rote Overlay (gefüllt mit entsprechendem Text) dann nach unten sliden lässt.
So etwas hatte ich schon vermutet, und das ist in der Tat ein Grund, relative Positionierung zu verwenden. Ich versuche mal, eine Alternative ohne Javascript heraus zu finden.
-
Nein, es ist nicht so, dass das ganze Skript falsch aufgebaut ist. Nur ist in diesem Fall der Ansatz mit dem Eventlistener nicht anwendbar. Die Frage und die Antworten werden ja durch Ajax geladen und dort hast Du schon einen Callback für den Fall, dass die Antwort vom Server da ist. Wenn Du dann das HTML fertig aufgebaut hast, kannst Du die Berechnung(en) mit Javascript durchführen:
Code
Alles anzeigenfunction makeQuestion(countofquestions) { const oneQuestion = new FormData(); oneQuestion.append('id', i); fetch('getQuestions.php', { method: 'post', body: oneQuestion }).then(questions => { return questions.json(); }).then(questions => { // Antwort vom Server ist da und dekodiert. count.innerHTML = i + '. Frage:'; question.innerHTML = questions.question; for (let j = 0; j < questions.answers.length; j++) { document.getElementById(j + 1).style.display = 'block'; document.getElementById(j + 1).innerHTML = questions.answers[j]; // Hier ist das HTML fertig und Du kannst deine Berechnungen durchführen. // Der Rest wie bisher: document.getElementById(j + 1).addEventListener('click', () => { const answerNumber = document.getElementById(j + 1).getAttribute('id'); // usw.Dazu noch eine Bemerkung: In vielen, nicht allen, Fällen sind solche Berechnungen von Abmessungen mit Javascript nicht notwendig weil man das Ziel auch mit CSS erreichen kann. Mach doch Mal eine statische Demo von dem Layout und beschreibe, was Du erreichen willst. Dann kann man prüfen, ob es auch mit CSS geht.
-
PS, ich vergaß: Bei meinen Tests war es manchmal so, dass bei einem Neuladen der Seite alles OK war, kein roter Balken zu sehen. Auch erst Mal unverständlich aber bei einem Neuladen holt der Browser die Schrift aus dem Cache, so dass sie schon da ist wenn das Javascript dran kommt.