Die Codes sind nicht identisch.

1) Der Starttag des urlset-Elements ist unvollständig. Es fehlt die schließende Klammer (>).

2) Es gibt mehrere ungeschlossene br-Elemente, bei denen eh hinterfragt werden müsste, was die in dem XML-Konstrukt bewirken sollen.

Berücksichtige, dass XML nicht gleich HTML ist. In HTML gibt es einen vordefinierten Satz bekannter Elemente, mit denen die Struktur einer Webseite beschrieben werden soll. Dort ist br bekannt. In XML ist es das nicht.

Für den Aufbau deiner Sitemap-XML solltest du dich an dem üblichen Schema orientieren. Es wird auf https://www.sitemaps.org/protocol.html beschrieben.

3) Es gibt mehrere öffnende url-Tags, die keinen schließenden Partner haben.

...zur Antwort

Für die Speicherung von Nutzereinstellungen kannst du PlayerPrefs nutzen.

Beispiel:

PlayerPrefs.SetInt("Some setting", 123);
PlayerPrefs.Save();

// somewhere else:
int defaultValue = 0;
int someSetting = PlayerPrefs.GetInt("Some setting", defaultValue);

Bezüglich der Kommunikation zwischen zwei Skripts ist die Zuweisung einer Referenz über den Inspektor eine einfache Methode.

Angenommen, du hast ein Skript A und ein Skript B. Skript A soll auf Skript B zugreifen. Dafür legst du in Skript A ein Feld mit dem Typ von Skript B an.

public ScriptB scriptB;

Im Editor wird daraufhin auf der Skriptkomponente ein Feld erscheinen, dem du via Drag & Drop das Skript / das GameObject mit dem Skript zuweisen kannst.

...zur Antwort
Sind diese PHP Methoden nützlich?

Hallo smarte Leute!

Bin PHP Neuling und habe mir dazu die ein oder andere hilfreiche Methode zusammengestellt und eine Standard DB Verbindung für eine MySQL Datenbank erstellt um diese möglicherweise auch für andere Projekte zu nutzen.

Sind diese Methoden hilfreich bzw. kann man diese verbessern?

Mfg, CodeMaster

Standartmethoden:

<?php
  
  function getContentSite($defaultSite) {


    if(isset($_GET['site']))
    {
      include_once($_GET['site'] . ".php");
    }
    else
    {
      include_once($defaultSite . ".php");
    }
  }


  function getFormAction()
  {
    if(isset($_GET["site"]))
    {
      return htmlspecialchars($_SERVER["PHP_SELF"]) . "?site=" . $_GET["site"];
    }


    return htmlspecialchars($_SERVER["PHP_SELF"]);
  }


  function getFormParam($name, $defaultVal = "") 
  {
    if(isset($_POST[$name]))
    {
      return $_POST[$name];
    }


    return $defaultVal;
  }


  function isFormValueChecked($key, $val)
  {
    return ($key == $val ? "checked"  : "");
  }


  function isFormValueSelected($key, $val)
  {
    return ($key == $val ? "selected"  : "");
  }


 ?>

Datenbankverbindung:

<?php


include_once("dbHelpers.inc.php");


$server = '';
$schema = '';
$user = '';
$password = '';


try{
    $con = new PDO('mysql:host='.$server.';dbname='.$schema.';charset=utf8',$user,$password);
    $con->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
} catch(Exception $e){
    printException($e);
}

Datenbankabfragen:

<?php


function makeStatement($query, $array = null){
    try{
        global $con;
        $stmt = $con->prepare($query);
        $stmt->execute($array);
        return $stmt;
    } catch(Exception $e) {
        printException($e);
    }
}
function printException($e)  {
    echo 'Error '.$e->getCode().$e->getMessage();
}


function makeTable($query, $arrV = null)
{
    try{
        $stmt = makeStatement($query, $arrV);
        echo '<table class="table">';
        $meta = array();
        echo '<tr>';
        for($i = 0; $i < $stmt -> columnCount(); $i++)
        {
            $meta[] = $stmt->getColumnMeta($i);
            echo '<th>'.$meta[$i]['name'].'</th>';
        }
        echo '</tr>';
 
        while($row = $stmt->fetch(PDO::FETCH_NUM)){
            echo '<tr>';
            foreach($row as $r){
                echo '<td>'.$r.'</td>';
            }
            echo '</tr>';
        }
        echo '</table>';
    }
    catch(Exception $e){
        printException($e);
    }
}

...zur Frage

Bei den Funktionen, die direkt Werte verarbeiten, die von außen kommen, wäre ich restriktiver. Für getContentSite sollte z.B. sichergestellt sein, dass wirklich nur die beabsichtigten PHP-Seiten aufgerufen werden können. Sammel die am besten in einem speziellen Ordner, in dem niemals andere PHP-Dateien abgelegt werden.

Da die Funktion versucht, die Datei direkt einzubinden, würde ich sie etwas anders benennen.

function includeContentSite($defaultSite) {
  if (!isset($_GET['site'])) {
    require_once($defaultSite . ".php");
    return;
  }

  $site = basename($_GET['site']);
  include_once('path/to/content/sites/folder' . $site . '.php');
}

Noch viel besser wäre allerdings ein Routingsystem, welches den Seitenname nicht an eine Datei, sondern eine Funktion knüpft. Zunächst werden alle Anfragen auf einen Dispatcher (index.php o.ä.) umgeleitet. Dort werden alle erwarteten URLs mit ihren zugehörigen Handlern verknüpft und gespeichert. Wenn die Request-URL auf einen bestimmten registrierten Eintrag passt, wird der dazugehörige Handler ausgeführt. Eine einfache Umsetzung wird in diesem Artikel gezeigt, andernfalls gibt es fertige (und ausgereiftere) Implementationen in diversen PHP-Frameworks (Laravel, Symfony, Yii, etc.).

Genauso solltest du restriktiver in getFormAction handeln. Schau erst, ob site einen validen, beabsichtigten Wert beinhaltet, bevor du ihn an eine Adresse hängst. Insofern könnte man sich da auch gleich eine Hilfsfunktion schreiben:

function getContentSiteName($defaultSite) {
  if (!isset($_GET['site'])) {
    return $defaultSite;
  }

  $site = basename($_GET['site']);
  $sitePath = 'path/to/content/sites/folder' . $site . '.php';

  if (file_exists($sitePath)) {
    return $site;
  }

  return $defaultSite;
}

function getFormAction() {
  $siteName = getContentSiteName('');

  if (!$siteName) {
    return $_SERVER['PHP_SELF'];
  }

  return '?site=' . $siteName;
}

Wenn es einen Querystring gibt, genügt diese relative Adresse. Andernfalls wird der aktuelle Dateiname ausgegeben, damit das action-Attribut, in welches der Wert später hineingeschrieben wird, nicht leer ist.

Hinsichtlich der Funktionen isFormValueChecked und isFormValueSelected kann ich nicht so viel sagen, da sich mir der Kontext nicht erschließt, in dem sie später eingesetzt werden.

Bei der Angabe des Connectionstrings würde sich, aufgrund der vielen Stringkonkatenationen eine Interpolation mal mehr lohnen:

$con = new PDO("mysql:host={$server};dbname={$schema};charset=utf8", $user, $password);

Und insgesamt könnte man alle Datenbankoperationen gut in einer Klasse kapseln:

class DatabaseHandler {
  public function __construct() {
    /* create PDO connection here ... */
    $this->connection = $connection;
  }

  public function makeStatement($query, $params = null) {
    try {
      $stmt = $this->connection->prepare($query);
      $stmt->execute($params);
      return $stmt;
    }
    catch(Exception $ex) {
      $this->printException($ex);
      return null;
    }
  }

  /* etc. */
}

// usage example:
$dbHandler = new DatabaseHandler();
$result = $dbHandler->makeStatement('select something from somewhere');
$otherResult = $dbHandler->makeStatement('select somethingElse from somewhereElse');

Auf eine globale Variable $con kann man somit verzichten. Die Rolle übernimmt das connection-Feld, welches nur in dem Kontext bekannt ist, in welchem es auch benötigt wird. Wenn du eine der Funktionen aufrufen möchtest, legst du dir eine Instanz der Klasse an und rufst über diese die jeweilige Funktion auf.

Achte im Übrigen darauf, konsistent bei der Werterückgabe zu sein. Wenn eine Funktion in einem ihrer Programmzweige einen Wert zurückgibt, dann sollte sie das letztendlich auch in allen anderen möglichen Programmzweigen tun.

Im obigen Fall (makeStatement) gibt es dahingehend zwei Möglichkeiten. Entweder du gibst bei Misserfolg null (oder zumindest einen anderen falsy Wert) zurück oder du verzichtest auf das try-catch und lässt eine Exception stattdessen nach oben eskalieren, um sie dann dort entsprechend zu behandeln.

Wenn du die erste Option wählst, könnte ein Aufrufer wie makeTable demzufolge so vorgehen:

public function makeTable($query, $arrV = null) {
  $stmt = $this->makeStatement($query, $arrV);

  if ($stmt) {
    /* print table ... */
  }
  else {
    /* fallback? */
}

Andernfalls bleibt es bei einem try-catch-Konstrukt.

Zu guter Letzt wäre es noch gut, die Namen einiger Bezeichner nochmals zu überdenken. Beispielsweise sollte $r doch eine Spalte repräsentieren und daher besser $column heißen. Bei $arrV oder $array wiederum ist von außen unklar, wozu sie dienen sollen. Ihr Zweck wird erst ersichtlich, wenn man sich den konkreten Code der jeweiligen Funktionen anschaut.

...zur Antwort

Das gesamte Konzept hinter Klassen/Objekte dient dazu, Probleme (bzw. Systeme) aus der tatsächlichen Welt besser/einfacher abbilden zu können. Es hilft dir zudem, dein Programm logisch zu strukturieren.

Ein gutes Beispiel wäre die Programmierung von Pac-Man. Es gibt ein Spielfeld, es gibt die Spielfigur, es gibt sammelbare Punkte und die Geister. Das sind alles Objekte in einem System, die (miteinander) agieren. Für jeden Objekttyp (Spielfigur, Geist, Punkt, ...) kann eine Klasse definiert werden, die die Eigenschaften (Felder) und Verhaltensweisen (Methoden) eines solchen Objekts beschreibt.

Z.b kann man Variablen auch mit einem Klassennamen deklarieren, statt mit einem einfachen Datentypen wie int oder String.

Java unterscheidet zwischen primitiven und komplexen Datentypen.

Primitive Datentypen verweisen auf einen einfachen, konstanten Wert. Zum Beispiel eine Zahl (s. int, float, double, ...).

Komplexe Datentypen hingegen können sich mehrere Eigenschaften merken und Methoden besitzen. Das heißt, sie benötigen mehr Speicherplatz und es wird eine Klasse benötigt, die ihren Aufbau beschreibt. Variablen komplexen Datentyps (z.B. String, Scanner, ...) verweisen somit auch immer auf ein Objekt.

Auch die Erzeugung eines neuen Objekts mit new bereitet mir Schwierigkeiten.

Du musst an sich nur wissen, welche Informationen ein Objekt braucht, um erstellt zu werden. Das lässt sich anhand des Konstruktors ablesen, der von der zugehörigen Klasse definiert wird. Bei Klassen aus der Standardbibliothek oder Klassen aus externen Bibliotheken u.ä. kannst du in der Regel in der jeweiligen Dokumentation nachschlagen, welche Konstruktoren eine bestimmte Klasse bietet.

Beim Erstellen des Objekts schreibst du nach dem new-Operator den Konstruktoraufruf. Der Konstruktor hat stets den selben Namen wie die Klasse.

Beispiel 1:

class Car {}

// main:
Car car = new Car();

Da in der Klasse kein expliziter Konstruktor definiert wird, wird der Standardkonstruktor verwendet, der parameterlos ist.

Beispiel 2:

class Car {
  public Car() {
  }
}

// main:
Car car = new Car();

Im Gegensatz zu Beispiel 1 wird explizit ein Konstruktor definiert (d.h. der Standardkonstruktor wird somit auch überschrieben). Der ist aber ebenfalls parameterlos, daher unterscheidet sich sein Aufruf nicht zu dem von oben.

Beispiel 3:

class Car {
  public Car(String color) {
  }
}

// main:
Car car = new Car("red");

Diesmal fordert der explizit definierte Konstruktor einen Parameter vom Typ String. Ohne diese Angabe kann kein Car-Objekt angelegt werden.

Beispiel 4:

class Car {
  public Car() {
  }

  public Car(String color) {
  }

  public Car(int maxVelocity) {
  }
}

// main:
Car car1 = new Car();
Car car2 = new Car("red");
Car car3 = new Car(250);

Die Klasse besitzt mehrere Konstruktoren. Somit kann man auch mit unterschiedlichen Daten Objekte der Klasse erzeugen.

...zur Antwort
Fehler bei password verify php?

Ich habe ein Testprogramm geschrieben, in dem man ein Passwort eingibt, dass dann gehasht in einer Datenbank gespeichert wird. Wenn ich mit dem Passwort vergleiche kommt aber nicht true sondern false raus. Das ganze habe ich in WebFTP gemacht.

Als Ausgabe bekomme ich:

123456789 $2y$10$4TMgUO3xGJMCy5iZnd6Be.TBRkIO2Z55GGwgQ5oeToD.ryJZAvvte Richtig In Datenbank übertragen $2y$10$4TMgUO3xGJMCy5iZnd6Be.TBRkIO2Z55GGwgQ5oeToD.ryJZAvvte Falsch Richtig übertragen

Bedeutet das gehashte Passwort wurde richtig gespeichert, aber passwort verify hat beim zweiten mal false zurück gegeben.

Hier ist der php Teil dazu:

<?php
if (isset($_POST["start"])) {
    $password = $_POST["password"];
    $email = $_POST["email"];
    echo $password . " ";
    $passwordHash = password_hash($password, PASSWORD_DEFAULT);
    echo $passwordHash . " ";
    if (password_verify($password, $passwordHash)){
        echo "Richtig ";
    }else{
        echo "Falsch ";
    }
    require_once "data.php"; //Hier wird die Datenbankverbindung gespeichert
    $statement = $pdo->prepare("INSERT INTO tab (email, password) VALUES (?, ?)");
    $statement->execute(array($email, $passwordHash));
    if ($statement){
        echo "In Datenbank übertragen ";
        $sql = "SELECT * FROM tab WHERE email='$email'";
        $user = $pdo->query($sql)->fetch();
        $passwordTest = $user["password"];
        echo $passwordTest . " ";
        if (password_verify($password, $passwordTest)){
            echo "Richtig ";
        }else{
            echo "Falsch ";
            if ($passwordHash == $passwordTest){
                echo "Richtig übertragen ";
            }else{
                echo "Falsch übertragen ";
            }
        }
        die();
    }else{
        die("Es ist etwas schief gelaufen");
    }
}
?>
...zur Frage

Vorweg: Ich kann dein Problem nicht reproduzieren.

Ein häufiger Grund, wenn ein Vergleich mittels password_verify fehlschlägt, liegt allerdings in intern unterschiedlich genutzten Zeichenkodierungen. Stelle daher sicher, dass du für die Datenkommunikation überall eine einheitliche Kodierung verwendest.

1) Gib dem Browser in dem HTML-Dokument, welches das Formular beinhaltet, eine Zeichenkodierung vor:

<meta charset="utf-8">

2) Deine Datenbank/-tabelle sollte die Daten in utf8mb4-Kodierung (= UTF-8) speichern.

3) Gib in deinem Connectionstring eine eindeutige Kodierung vor:

$connectionString = 'mysql:host=...;dbname=...;port=...;charset=utf8mb4';
...zur Antwort

Du kannst die Daten an ein Skript schicken, welches je nach gesetzter Checkbox die Daten anders verarbeitet.

Beispiel:

<form action="handle.php" method="post">
  <input name="data">
  <input name="other-target" type="checkbox">
  <input type="submit">
</form>

handle.php:

<?php
  if (isset($_POST['other-target'])) {
    include_once 'handleA.php';
  }
  else {
    include_once 'handleB.php';
  }

Alternativ könntest du die Daten auch erst in eine Session schreiben, dann weiterleiten und die Daten dann wieder aus der Session auslesen.

handle.php:

<?php
  session_start();

  $_SESSION['data'] = $_POST['data'];

  if (isset($_POST['other-target'])) {
    header('Location: handleA.php');
  }
  else {
    header('Location: handleB.php');
  }

Auslesen der Daten aus der Session:

<?php
  session_start();

  $data = $_SESSION['data'];
...zur Antwort

Möglicherweise befindet sich der Spinner außerhalb des sichtbaren Bereichs, weil er in irgendeiner Form überdeckt/abgeschnitten wird.

Ich würde erst einmal die Höhe und Breite des Pseudoelements anpassen (z.B. auf jeweils 20px), sodass man wieder erkennt, dass sich es sich um einen Kreis handeln soll. Dann wäre das Element auch so groß, sodass es über dem Text liegt. Wenn du einen roten Hintergrund verwendest, ändere auch die Rahmenfarben des Spinners.

Wenn das Element daraufhin noch nicht sichtbar ist, dann schau dir die Elemente im Webinspektor (in den Entwicklungstools deines Browsers) an. Zum einen sollte dem div-Element immer noch die loader-Klasse zugeordnet sein (andernfalls gibt es entweder ein Skript, welches dynamisch Einfluss auf das Element nimmt oder das initiale Markup, welches geladen wird, passt doch nicht). Zum anderen kannst du via Mouseover über dem Knoten des Pseudoelements sehen, wo es auf der Seite liegt (die entsprechende Fläche wird farblich im Browserfenster hervorgehoben).

(...) sondern egal was ich in der style.css definiere es erscheint das Wort "Ladebalken" auf weißem Grund.

Das Wort ist initial gesetzt. Via CSS kannst du es nicht wirklich entfernen (nur durch Ausblenden des kompletten Elements, was den Spinner inkludieren würde).

Solltest du bei deinen Versuchen gemerkt haben, dass sich das CSS, welches von der Seite geladen wird, nicht ändert, obwohl du die Datei modifiziert hast, dann wird die CSS-Datei wohl in einem Cache gehalten. Hänge nach jeder Änderung der Datei einen anderen Querystring an die Ressourcen-URL.

Beispiel:

<link href="style.css?v=123" rel="stylesheet">
...zur Antwort

Der Setter gewährt dir eine Schnittstelle, über die du den Wert des privaten Feldes setzen kannst. Praktischerweise könntest du so auch zusätzliche Logik implementieren, die beispielsweise den neuen Wert zuerst auf Validität prüft.

Beispiel:

class Person {
  private int age;

  public void setAge(int age) {
    if (age > 0 && age <= 122) {
      this.age = age;
    }
  }
}
...zur Antwort

Die Datei wurde mit dem All-in-One WP Migration and Backup-Plugin generiert. Mit diesem Plugin kannst du die Daten auch wieder importieren.

https://www.youtube.com/watch?v=BpWxCeUWBOk

...zur Antwort
wie behebe ich diesen fehler?

Hallo!

Kann mir jemand helfen diese Fehler zu beheben?

FEHLER 1 :Traceback (most recent call last):

 File "C:\Users\arrou\OneDrive\Desktop\cheese\für acc\tmmail\main.py", line 37, in <module>

class mailtm_gui(ctk.CTk):

Fehler 2 :  File "C:\Users\arrou\OneDrive\Desktop\cheese\für acc\tmmail\main.py", line 59, in mailtm_gui

  knopf = ctk.CTkButton(main, text="n", command=neum())

FEHLER 3 :  File "C:\Users\arrou\OneDrive\Desktop\cheese\für acc\tmmail\main.py", line 56, in neum

  mail_body = ctk.CTkEntry(mail_window, placeholder_text='Subject: ' + message['subject'] + '\nBody: ' + (message['text'] if message['text'] else message['html']), width=900, font=('Helvetica', 20))

TypeError: 'module' object is not subscriptable

import customtkinter as ctk
from mailtm import *
from mailtm import message


def listener(message):
    print("\nSubject: " + message['subject'] + str(listener))
    print("Content: " + message['text'] if message['text'] else message['html'] + str(listener))


test = Email()
print("\nDomain: " + test.domain)

test.register()
print("\nEmail Adress: " + str(test.address))


test.start(listener, interval=3)
print("\nHab Sabr.....")


main = ctk.CTk()
main.geometry("500x320")
main.title("Temp mail By Amjn")


emaila = ctk.CTkEntry(main, placeholder_text="         " + test.address, width=900, font=("Helvetica", 20))
emaila.configure(state="readonly")
emaila._corner_radius = 10
emaila.pack()


Copyt = ctk.CTkLabel(main, text="Copy Email", font=("Helvetica", 20))
Copyt.pack()


class mailtm_gui(ctk.CTk):
    def __init__(self):
        ctk.CTk.__init__(self)
        self.geometry('500x320')
        self.title('Temp mail By Amjn')
        listener = Email()
        listener.register()
        emaila = ctk.CTkEntry(self, placeholder_text=listener.address, width=900, font=('Helvetica', 20))
        emaila.configure(state='readonly')
        emaila._corner_radius = 10
        emaila.pack()
        listener.start(listener, interval=3)

    def neum():
        mail_window = ctk.CTkToplevel()
        mail_window.title("amjs tm by mailtm")
        mail_window.geometry('500x320')
        mail_window.corner_radius = 30
        mail_window.resizable(width=True, height=True)
        mail_body = ctk.CTkEntry(mail_window, placeholder_text='Subject: ' + message['subject'] + '\nBody: ' + (message['text'] if message['text'] else message['html']), width=900, font=('Helvetica', 20))
        mail_body.pack()

    knopf = ctk.CTkButton(main, text="n", command=neum())


main.mainloop()
...zur Frage

1) Bei der Definition des command für deinen Button rufst du die Funktion neum direkt auf. Das heißt, ihr Rückgabewert (None) wird anschließend dem Argument command zugewiesen.

Richtig wäre die Übergabe einer Funktionsreferenz:

knopf = ctk.CTkButton(main, text="n", command=neum)

2) Die Fehlermeldung

TypeError: 'module' object is not subscriptable

weist daraufhin, dass du ein Modul so behandelst, als sei es ein Objekt.

Beispiel:

# --- a.py ---
a = { "test": 123 }

# --- b.py ---
import a
print(a["test"]) # error: a is the module, not the dict

# --- c.py ---
import a
print(a.a["test"]) # 123

# --- d.py ---
from a import a
# or: from a import *
print(a["test"]) # 123
...zur Antwort

Konsoleneingaben kannst du mit einer Scanner-Instanz lesen.

Scanner reader = new Scanner(System.in);
String input = reader.next();

Einen String kannst du mittels if und equals prüfen.

String firstWord = "first";
String secondWord = "second";

if (firstWord.equals(secondWord)) {
  // ...
}

Für Textausgaben auf der Konsole gibt es println.

System.out.println("Some output");
...zur Antwort

Du rufst die toogleTopnav-Funktion nirgendwo auf. Die Funktion myFunction wird wohl auch nicht definiert.

Noch ein paar weitere Anmerkungen:

  • Es gibt Elemente wie header oder nav, mit denen dein Markup besser strukturiert werden könnte, als nur mit div-Elementen
  • Für den Menübutton würde ich auch ein button-Element (type="button") verwenden, statt einen Link; via CSS kann er genauso gut nach Bedarf visuell angepasst werden
  • Dein Logolink hat keinen Linktext. Füge ihn entweder (z.B. in einem inneren span-Element) hinzu und blende ihn visuell aus oder setze ihn im alt-Attribut des Bildes
  • So lange du nur Text setzt, ist das textContent-Property passender als innerHTML
...zur Antwort
Es sind aber noch alle Daten auf Dem SQL Server da. Reicht das, um die Seite wieder online zu bekommen?

Nein. In der Datenbank sind doch andere Daten gespeichert, als in den Dateien, die gelöscht wurden.

Der Hoster meint, sie sei gelöscht worden. Nur wie?

Vielleicht kann dir der Hoster mehr Informationen liefern.

Auf deiner Seite wäre es nicht unklug zu prüfen, wer Zugriff auf deinen Rechner hat und es wäre gut, die Anmeldedaten des Webspace-Accounts zu ändern.

Was mache ich jetzt?

Frage beim Webhoster, ob es ein Backup gibt. Wenn dem nicht der Fall ist, musst du selbst schauen, wie du von deiner Seite aus die Daten wiederbeschaffen kannst (neu entwickeln oder möglicherweise hast du sie noch irgendwo vorliegen).

Für die Zukunft solltest du definitiv immer ein Backup der zuletzt hochgeladenen Daten bei dir selbst hinterlegen.

...zur Antwort
HTML/CSS/JS: Warum funktioniert meine bindDelete-Funktion nicht und wie kann ich die Preisangaben untereinander formatieren?

Hi, ich habe an einen Spezialisten eine Frage:

import Order from './Order.js';
import ArticleModel from './ArticleModel.js';

export default function UserOrderViewHandler(articleModel) {
  this.articleModel = articleModel;
  this.order = new Order(-1, null, [], 0, 0, 0, 0, 0, false);
}

UserOrderViewHandler.prototype.renderPage = function() {
  let body = document.getElementsByTagName('body')[0];
  body.innerHTML = "";
  body.innerHTML = `<div class="container">
    <sidebar>
      <h1 class="mb-4">Unser Sortiment</h1>
      <div id="articleList">
        <div class="row space-between">
          <div class="col-md-4 mb-4">
            <div class="card" data-index="0">
              <div>
                <h2>Salamipizza</h2>
                <p>Halbe hausgemachte Pizza mit Käse und regionaler Salami</p>
                <p><strong>6.50 €</strong></p>
                <button class="addBtnClss btn btn-primary">Artikel hinzufügen</button>
              </div>
            </div>
          </div>
          <div class="col-md-4 mb-4">
            <div class="card" data-index="1">
              <div>
                <h2>Hamburger</h2>
                <p>Burger mit österreichischem Rindfleisch, Ketchup und Senf</p>
                <p><strong>6.00 €</strong></p>
                <button class="addBtnClss btn btn-primary">Artikel hinzufügen</button>
              </div>
            </div>
          </div>
          <div class="col-md-4 mb-4">
            <div class="card" data-index="2">
              <div>
                <h2>Wochenmenü</h2>
                <p>Frittatensuppe --- Spaghetti Bolognese --- Muffin</p>
                <p><strong>12.50 €</strong></p>
                <button class="addBtnClss btn btn-primary">Artikel hinzufügen</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </sidebar>
    <sidebar>
      <h1 class="mb-4 extramargin">Bestellung</h1>
      <ul id="order"></ul>
      <div class="form-group">
        <label for="pickupTime">Gewünschte Abholzeit:</label>
        <input type="time" id="pickupTime" class="form-control">
      </div>
    </sidebar>
  </div>`;
}

UserOrderViewHandler.prototype.renderOrder = function() {
  let orderElement = document.getElementById('order');
  orderElement.innerHTML = "";
  orderElement.className = "list-group";

  let i = 0;

  for (let article of this.order.articleList) {
    let articleElement = document.createElement('li');
    articleElement.className = "list-group-item d-flex justify-content-between align-items-center";
    articleElement.innerHTML = `
      <div>1 x ${article.name} &emsp; &emsp; &emsp;${article.price.toFixed(2)} €</div>
      <button class="delBtn btn btn-danger btn-sm" data-index="${i}">Entfernen</button>
    `;
    orderElement.appendChild(articleElement);
    i++;
  }
}

UserOrderViewHandler.prototype.bindAddBtn = function() {
  let buttons = document.getElementsByClassName('addBtnClss');
  const that = this;

  for (let button of buttons) {
    button.addEventListener('click', function() {
      let index = this.closest('.card').getAttribute('data-index');
      let article = that.articleModel.getByIndex(index);

      if (article) {
        that.order.addArticle(article);
        that.renderOrder();
      }
    });
  }
}

UserOrderViewHandler.prototype.bindDeleteBtn = function() {
  let orderElement = document.getElementById('order');
  orderElement.addEventListener('click', function(event) {
    if (event.target.classList.contains('delBtn')) {
      let index = event.target.getAttribute('data-index');
      that.order.deleteArticle(index);
      that.renderOrder();
    }
  });
}
  1. Warum funktioniert meine bindDelete-Funktion nicht, um die li-Elemente wieder zu löschen?
  2. Wie kann ich es schaffen, dass der Preis von jedem li-Element genau so untereinander ist, sodass man ihn schön zusammenrechen könnte:

Danke für die Hilfe.

...zur Frage
Warum funktioniert meine bindDelete-Funktion nicht, um die li-Elemente wieder zu löschen?

Die Variable that wird von dir nicht definiert. Entweder du packst die Definition mit an den Funktionsanfang:

const that = this;

oder du nutzt zum einen eine Arrow-Funktion, um den Event Handler zu definieren und zum anderen this statt that.

button.addEventListener('click', () => {
  /* ... */
  this.order.addArticle(article);
  this.renderOrder();
Wie kann ich es schaffen, dass der Preis von jedem li-Element genau so untereinander ist, sodass man ihn schön zusammenrechen könnte:

Es gibt verschiedene Wege:

  • Verwende keine Liste, sondern eine Tabelle mit festen Spaltenbreiten; ordne Name, Preis und Button dabei in unterschiedliche Spalten ein
  • Packe die jeweiligen Angaben (Name, Preis) in einzelne (span-)Elemente. Gib denen mit CSS (width) eine entsprechende Breite oder ordne die Elemente mit einem CSS Grid an (via grid-template-columns kannst du die Spaltenbreiten vorgeben)

Zusätzlich wäre es wohl besser, die Preise mit CSS rechtsbündig auszurichten (text-align: right).

Zuletzt noch ein paar Anmerkungen zu deinem restlichen geteilten Code:

1) Diese Zeile ist überflüssig:

body.innerHTML = "";

Du überschreibst den Inhalt des body-Elements doch im Anschluss gleich noch einmal.

Wenn der Inhalt, den du in renderPage setzt, im Übrigen initial beim Laden der Seite angezeigt werden soll, würde ich ihn auch nicht dynamisch mit JavaScript einbinden, sondern direkt von Anfang an im body-Bereich ausliefern.

Mehr Sinn würde es m.E. machen, die konkreten Inhalte (Artikelname, Beschreibung, Preis, ID) in ein JSON-Objekt auszulagern und dann die einzelnen Artikelelemente via Schleife zu generieren. Statt mit innerHTML zu arbeiten, würde sich ein template-Element für diesen Fall gut eignen.

2) Es gibt kein HTML-Element namens sidebar. Naheliegend zu dem wäre ein aside-Element.

3) Solltest du strong allein aus dem Grund nutzen, den Preis visuell zu formatieren, dann entferne es und style den Text stattdessen mit CSS (siehe font-weight).

...zur Antwort

Ein Weg wäre die Installation des DuckDB CLI. Lade die passende Version für dich herunter und entpacke sie. Die Datenbankdatei würde ich im Anschluss (der Einfachheit halber) direkt mit in das Verzeichnis kopieren.

Öffne im Anschluss die Kommandozeile deines Betriebssystems (meine folgenden Code-Snippets beziehen sich auf Windows OS) und navigiere zu dem entpackten Ordner, in dem die duckdb.exe liegt.

cd "c:/path/to/duckdb/folder"

Dann kannst du auch schon eine Verbindung herstellen:

duckdb hotelkette.db

Sollte deine Datenbankdatei doch noch in einem anderen Pfad liegen, gib stattdessen den absoluten Dateipfad an. Am besten umklammert von Anführungszeichen, falls einer der Verzeichnisnamen ein Leerzeichen enthalten sollte.

duckdb "c:/path/to/hotelkette.db"

Sobald sich der Client mit der Datenbank verbunden hat, solltest du via SQL Daten auslesen oder schreiben können. Der beste Startpunkt wäre wohl, erst einmal in Erfahrung zu bringen, was für Tabellen überhaupt in der Datenbank liegen und wie sie strukturiert sind.

Die information_schema_tables-View beinhaltet bspw. Informationen über alle verfügbaren Tabellen in der Datenbank:

SELECT table_name FROM information_schema.tables

Die Struktur einer bestimmten Tabelle kannst du in Erfahrung bringen, indem du in der information_schema.columns-View nach der Tabelle suchst:

SELECT * FROM information_schema.columns WHERE table_name = 'name of a table'

Mehr zu den information_schema-Views kannst du in der Dokumentation nachschlagen.

Alternativ zu diesem Weg macht es dir DBeaver an der Stelle natürlich deutlich einfacher. Auf deinem ersten Screenshot hast du die Datenbank ja bereits geöffnet. Wenn du im linken Dialog (Datenbanknavigator) die Knoten von beispielsweise main oder pg_catalog einmal aufklappen würdest, solltest du ebenso die Tabellen finden, die in der Datenbank so vorliegen.

Explizit relevant für dich sind natürlich nur die Tabellen, die irgendetwas mit Hotels zutun haben.

Sollte dir nun aber noch Wissen zu dem Aufbau von Datenbanktabellen fehlen (z.B. Was Constraints oder Datentypen sind), würde ich dir empfehlen, dich dazu erst einmal zu belesen. Hilfreiche Artikel gibt es zum Beispiel auf datenbanken-verstehen.de. Bezüglich der SQL-Syntax solltest du in der DuckDB-Dokumentation nachschlagen.

(...) um an dieser Datei neue Dinge hinzuzufügen (...)

Neue Daten kannst du mittels INSERT INTO zu einer bestehenden Tabelle hinzufügen.

Beispiel:

Angenommen, wir haben eine Tabelle hotelpersonal, die das Hotelpersonal auflisten soll. Es gibt die Spalten vorname (VARCHAR), nachname (VARCHAR), gehalt (DECIMAL) und position (VARCHAR).

Das Hinzufügen eines neuen Datensatzes könnte folgendermaßen aussehen:

INSERT INTO hotelpersonal (vorname, nachname, gehalt, position)
VALUES ('Zéro', 'Moustafa', 2400, 'Page');

Für Weiteres dazu würde ich erneut auf die DuckDB-Dokumentation verweisen.

...zur Antwort

Schau nach, wo die Variable vorkommt (z.B. mittels Volltextsuche o.ä. Editorfunktionen) und wie ihr Werdegang ist. Bei einer Fehlermeldung seitens des Programms solltest du auch schon Informationen dazu bekommen, zu welchem Zeitpunkt die Variable ohne Wert ist.

Letzten Endes musst du dann natürlich schauen, dass ihr ein entsprechender Wert zugewiesen wird.

...zur Antwort
HTML: Wie kann ich die Titelbox verschieben?

Hey,

ich verzweifle mittlerweile an meinen eigenen Sinnen und hab schon manches probiert. Das Einbinden von KI (ChatGPT) hat mir dann den Rest gegeben, da alles was davon kam einfach keinen Sinn ergab.

Ich habe zwei Container, also left-colum und right-colum.

Wie man in dem Code sehen kann, wird die Klasse "whatis-titlebox" im ersten Teil korrekt angezeigt. Es wird das Szenario eintreten, dass die linke Spalte leer beiben wird und nur die rechte mit Text gefüllt wird.

Dazu dachte ich mir, kopiere ich den Standardteil und spreche die Kopie dann mit "rightinput" um eben "whatis-titlebox" aus dem 2. Teil, also "rightinput whatis-titlebox" über die rechte colum zu legen, sodass der Text darin linksbündig mit dem Text sichtbar wird. Fehlanzeige, ich habe es nicht geschafft. Vielleicht ist mein Code auch einfach nur falsch geschrieben.

Ich blicke da nicht mehr durch und hoffe, dass ich hier Hilfe erhalte.

HTML:

<div class="leidfadenmain-input">
    <div class="whatis">
        <div class="whatis-titlebox">
            <h2 class="whatis-title-txt">Über</h2>
        </div>
        <div class="container">
            <div class="left-column">
                <!-- Linker Text -->
                <p class="whatis-txt"></p>
                <p class="whatis-txt"></p>
            </div>
            <div class="divider"></div>
            <div class="right-column">
                <!-- Rechter Text bei Bedarf -->
                <p class="whatis-txt"></p>
            </div>
        </div>
    </div>

    <div class="whatis">
        <div class="rightinput whatis-titlebox">
            <h2 class="whatis-title-txt">Über</h2>
        </div>
        <div class="container">
            <div class="left-column">
                <!-- Linker Text -->
            </div>
            <div class="divider"></div>
            <div class="right-column">
                <!-- Rechter Text bei Bedarf -->
                <p class="whatis-txt"></p>
            </div>
        </div>
    </div>
</div>

CSS:

.leidfadenmain-input {
    padding-top: 100px;
    display: flex;
    flex-direction: column;
}

.whatis {
    display: flex;
    flex-direction: column; /* Ändert die Ausrichtung auf vertikal */
    width: 100%;
    max-width: 1000px;
    margin: 0 auto;
}

.whatis-txt {
    padding-bottom: 15px;
}

.whatis .whatis-titlebox {
    position: relative;
    margin-bottom: 20px;
    top: 0;
}

.rightinput .whatis-titlebox {
    margin-bottom: 20px;
    top: 0;
    left: 50%; /* Zentriert die Überschrift horizontal */
    transform: translateX(-50%); /* Zentriert die Überschrift horizontal */
}

.whatis .whatis-title-txt {
    font-size: 1.5em;
    font-weight: bold;
    margin-bottom: 10px;
}

.whatis .left-column,
.whatis .right-column {
    width: 45%;
}

.whatis .divider {
    width: 1px;
    height: auto;
    background-color: black; /* Ändere die Farbe bei Bedarf */
    margin: 0 10px;
}

.whatis .container {
    display: flex;
    align-items: stretch;
    width: 100%;
}

Einfach erklärt.: ".rightinput .whatis-titlebox" soll, sofern gebraucht, über right-colum platziert werden.

Sofern ihr mir weiterhelfen könntet, wäre ich euch dankbar!

Vielen Dank!

Liebe Grüße

...zur Frage

Wenn die linke Spalte nicht gebraucht wird, sollte sie auch nicht herausgerendert werden. Das heißt, der Browser sollte in diesem Fall nur so ein Markup für den Container erhalten:

<div class="container">
  <div class="right-column">
    <!-- ... -->
  </div>
</div>

Da du das HTML offensichtlich selbst definierst, sollte das kein Problem darstellen.

Im Notfall könnte man auch die linke Spalte mitsamt Trenner via CSS ausblenden, vorausgesetzt, das Element ist tatsächlich leer (keinerlei Kindelemente oder Text, inklusive Leerzeichen):

.whatis .left-column:empty,
.whatis .left-column:empty + .divider {
  display: none
}

Die linke Spalte hingegen leer, aber sichtbar mitsamt Trenner herauszurendern und die Überschrift über die rechte Spalte zu verschieben, erscheint für mich unlogisch. Zum einen zeigst du dann überflüssige Inhalte an (die von einem Seitenbesucher vermutlich als unästhetisch und fehlerhaft gewertet werden) und zum anderen unterbricht es den Lesefluss.

Wenn du es aber unbedingt erzwingen möchtest, wäre es besser, der Titelbox (.whatis-titlebox) eine zusätzliche Modifikatorklasse zuzuweisen, mit der sie verschoben wird.

Beispiel:

<div class="whatis-titlebox whatis-titlebox-right">
  <h2 class="whatis-title-txt">Über</h2>
</div>

CSS:

.whatis-titlebox-right {
  margin-left: calc(45% + 1px);
}

Elemente zu duplizieren und dann übereinanderzuschieben ist keine gute Idee.

...zur Antwort

PyCharm verwendet eine eigene Konsolenimplementation, die sich nicht direkt so verhält, wie du es bei der Windows Konsole erwarten könntest. Aufrufe wie cls funktionieren in ihr nicht. Wenn du den Fensterinhalt leeren möchtest, musst du auf die GUI-Funktionalitäten von PyCharm zurückgreifen (z.B. Rechtsklick in das Konsolenfenster > Clear All).

Die IDE stellt allerdings auch eine Einstellung bereit, mit der eine OS-Konsole zumindest emuliert werden kann (siehe: Emulate terminal in output console in den Run/Debug Configurations). Wenn du die aktivierst, sollte ein Aufruf wie

import os
os.system("cls")

die Konsole leeren.

Für eine tatsächliche Sicherheit, dass all deine Anweisungen an die Konsole wie erwartet funktionieren, solltest du dein Python-Skript allerdings in der echten Konsole von Windows ausführen.

...zur Antwort

Direkt schreiben/definieren kannst du Methoden immer nur innerhalb einer Klasse oder einem Interface. Objekte sind die Instanzen von Klassen, die sich später auf bestimmte Methoden beziehen können, die in der Klasse (oder einer Basisklasse) definiert wurden.

Beispiel:

class Car {
  public void drive() {
    System.out.println("Wrumm wrumm");
  }
}

// main:
Car herbie = new Car();
herbie.drive();

Hier wird eine Klasse Car angelegt, in der eine Methode drive definiert wird. Später kann ein Objekt dieser Klasse kreiert werden. Dieses Objekt hat Zugriff auf die Methode drive.

Weiterführend wird bei Methoden, die du in einer Klasse definierst, grundsätzlich zwischen objektgebundenen (Instanz-) und klassengebundenen (statischen) Methoden unterschieden. Letztere werden mit dem static-Modifier gekennzeichnet.

Beispiel:

class Car {
  public static int compareCars(Car car1, Car car2) {
    // ...
  }
}

// main:
Car herbie = new Car();
Car docHudson = new Car();
Car.compareCars(herbie, docHudson);

Der wesentliche Unterschied bei statischen Methoden liegt darin, dass sie über die Klasse aufgerufen werden. Das heißt, du brauchst kein Objekt für einen Aufruf und innerhalb ihres Körpers gibt es keine this-Referenz (d.h. es besteht kein Zugriff auf objektgebundene Elemente), so wie in objektgebundenen Methoden.

Welche Methodenart je Fall passend ist, kann logisch erfragt werden. Verhaltensweisen/Aktionen, die ein Objekt ausmachen, sollten bspw. objektgebunden definiert sein.

...zur Antwort