Probleme beim +/- Button und der Veränderung des Wertes einer Variablen

  • Rahmenbedingungen


    Browser & Betriebssystem: Firefox 43.0.4,Windows 7


    Editor: Microsoft Expression Web 4

    Meine Kenntnisse zum Thema Webseitenerstellung: totaler Anfänger


    Ich verfüge nicht über PHP und MySQL.


    Hallo ihr lieben!
    Ich habe große Probleme bei der Erstellung des Webshops und hoffe, dass ihr mir helfen könnt.


    Problembeschreibung


    Fehlermeldung/-beschreibung: Wir sollen für die Uni in einer Gruppe einen Webshop erstellen. Der Webshop soll jedoch nicht als richtige Webseite online gehen. Wir sollen ihn nur erstellen. Ich bin für die Funktionen des Warenkorbs zuständig. Mein Warenkorb soll später so aussehen, dass ein Kunde seine Lieferdaten, die gewünschte Zahlungsoption, die Anzahl der Artikelt im Warenkorb über ein Formular übermittelt und meine E-Mail-Adresse weitergeleitet werden.
    Hier habe ich mehrere Probleme. Eines dieser Probleme ist, dass ich einen Plus- und Minusbutton für jedes unserer vier Produkte erstellen möchte, welche die aktuelle Anzahl der Artikel im Warenkorb um eins erhöhrt bzw. um eins verringert.


    Der InternetExplorer kann meine bereits erstellte Funktion gar nicht umsetzen. Firefox setzt die Funktionen der Plus- und Minusbuttons um, erzeugt jedoch folgende Fehler:
    a) Wenn ich auf den Plusbutton klicke, dann wird die Anzahl des gewählten Artikels um eins erhöht. Wenn ich jetzt aber auf den Minusbutton klicke, dann wird die Anzahl des Artikels zunächst ebenso um den Wert eins erhöht. Erst beim zweiten Klick auf den Minusbutton, wird der Wert des Artikels gesenkt.


    b) Analog zum ersten Problem (nur umgekehrt): Wenn ich auf den Minusbutton klicke, dann wird die Anzahl des
    gewählten Artikels um eins gesenkt. Wenn ich jetzt aber auf den Plusbutton klicke, dann wird die Anzahl des Artikels zunächst ebenso um
    den Wert eins gesenkt. Erst beim zweiten Klick auf den Plusbutton, wird
    der Wert des Artikels erhöht.


    Ich habe tagelang nach den Fehlern gesucht. Da ich jedoch wirklich nur einige wenige Kenntnisse zu HTML und Java-Script habe, konnte ich den Fehler nicht finden. Auch die Recherche hierzu in verschiedenen Foren brachte mir keine Lösung für mein Problem.
    Ich suche also nach einer Lösung, welche nicht Browserabhängig ist und ebenso den Fehler bezüglich der Erhöhung und der Senkung der Artikelanzahl beseitigt.


    (Die eigentliche Formattierung des Webshops bezüglich des Layouts habe ich nur für mich erstellt. Sobald die Funktionen innerhalb des Webshops funktionieren, werde ich diese an das Gruppenmitglied weiterreichen, welches mit CSS arbeitet.)

    Code:


    Über eure Hilfe würde ich mich sehr freuen!

  • Das Verwenden des ++ und -- Operators in Ausdrücken hat so seine Tücken:

    JavaScript
    variable2 = variable1++;

    Der Wert von variable1 wird dem Wert von variable2 zugewiesen und hinterher erhöht. Das erklärt genau deine Probleme.
    Bei

    JavaScript
    variable2 = ++variable1;

    Hier wird der Wert vor der Zuweisung erhöht und das müsste deine Probleme lösen.

  • Hallo HTML-Anfaenger, zunächst ein mal vielen Dank für deine ausführliche Problembeschreibung.


    Ich empfehle dir zuerst, deinen Javascript Code möglichst aus dem HTML Code herauszuhalten. Besonders wenn verschiedene Personen an einem Werk arbeiten ist eine saubere Trennung hilfreich. Dabei möchte ich dir natürlich gerne helfen. Zunächst habe ich deinen Code etwas abgeändert und eine solide Basis geschaffen.


    Wegen der Übersicht habe ich viele für unser Vorhaben unnötige Informationen herausgenommen, die du hinterher natürlich wieder einfügen kannst.
    Außerdem habe ich sämtliches Javascript entfernt, dafür habe ich den Buttons aussagekräftigere Namen gegeben, den Aufbau erkläre ich später.
    Zusätzlich hat jeder Button die Klasse "action_button" erhalten, auch das wird weiter unten geklärt.


    Bis dahin der Code:



    Sämtlichen Javascript Code fügen wir nun in den Script-Tag (Zeile 24-26) ein.


    Jetzt zum Programm an sich:


    Elemente auswählen
    Du fragst dich nun sicher, woher Javascript jetzt wissen soll wann ein Button geklickt wird. Dafür benutzen wir Selektoren aus dem document-Objekt von Javascript und so genannte EventListener. EventListener machen genau das selbe wie zum Beispiel ein onclick Attribut im HTML Code.


    Selektieren:

    JavaScript
    document.getElementById();
    document.getElementsByClassName();
    document.getElementsByName();
    document.getElementsByTagName();


    Es fällt direkt auf, dass beim Wort "Element" in den letzten 3 Fällen der Plural genutzt wird, das bedeutet im Klartext: Es können mehrere Elemente zurückgegeben werden. Wenn die Seite 3 p-Elemente beinhaltet, resultiert document.getElementsByTagName("p"); in einem Array mit allen 3 Elementen. Ein Array ist eine Variable, die mehrere Variablen enthalten kann. Alles dazu kannst du hier nachlesen.


    EventListener:

    JavaScript
    // var meinElement enthält ein durch document.getElement... selektiertes Element
    meinElement.addEventListener("click", function(e){
        // Was passieren soll, wenn das Element geklickt wird
    });


    Der Aufbau wird dir auf den ersten Blick eventuell sehr fremd vorkommen, wenn man ein paar mal damit gearbeitet hat ist das Ding aber gar nicht mehr so schwer. Bei Klick wird eine anonyme Funktion aufgerufen. Das heißt eine Funktion ohne Namen, alles zu Funktionen kannst du hier lesen.


    Reihenfolge
    Javascript wird im obigen Code nun vor dem HTML Code verarbeitet. Das heißt wenn wir Selektoren (document.getElement...) benutzen, gehen die ins Leere, da die HTML Elemente noch nicht geladen sind. Entweder packen wir den Javascript Code hinter den HTML Code, oder wir nutzen einen kleinen Trick:


    JavaScript
    window.onload = function(){
        // Sämtlicher Javascript Code
    }


    Auch hier wieder eine anonyme Funktion, welche durch einen EventListener (dies mal auf noch eine andere Art) ausgelöst wird. Nämlich genau dann, wenn der gesamte Fensterinhalt geladen ist.


    Aufbau des Scripts
    Zuerst den Ablauf klarmachen:

    • Javascript muss alle Buttons überwachen
    • Button wird geklickt
    • Javascript stellt fest welcher Button geklickt wird
    • Entsprechendes Input Feld wird verändert

    Punkt 1 ist hier der absolut schwierigste für Anfänger.


    Wie Elemente mittels Javascript ausgelesen werden ist bereits klar, also kann damit auch angefangen werden. Jeder wichtige Button hat die Klasse "action_button", also bietet sich getElementsByClassName an:


    JavaScript
    window.onload = function(){
        var buttons = document.getElementsByClassName("action_button");
    }


    In der Javascript Konsole (hier unter Punkt 3 eine Erläuterung) enthält die button Variable nun 8 button-Elemente:


    Code
    HTMLCollection [ 
    	0: <input.action_button>, 
    	1: <input.action_button>, 
    	2: <input.action_button>, 
    	3: <input.action_button>, 
    	4: <input.action_button>, 
    	5: <input.action_button>, 
    	6: <input.action_button>, 
    	7: <input.action_button> 
    ]


    Wenn man jetzt einen EventListener hinzufügen will, muss man das Array zunächst in einer Schleife durchlaufen. Eine Schleife führt eine bestimmte Aktion bis zu einem gewünschten Ereignis immer wieder aus. Da die Elemente des Arrays mit Zahlen in aufsteigender Abfolge angesprochen werden können, empfiehlt sich die for-Schleife (alle Infos hier:(


    JavaScript
    for(var i = 0; i < buttons.length; i++)
    {
        //buttons[i].addEventListener...
    }


    Zum nachvollziehen:

    • Der Variable i wird der Wert 0 zugewiesen (das erste Element im Array hat den Index 0)
    • Danach kommt die Bedingung, wie lange die Schleife laufen soll (i < buttons.length). "length" gibt die Anzahl der Elemente im Array zurück (8).
    • Danach der Befehl zum erhöhen von i (wird nach jeder Iteration ausgeführt).
    • Z. Dt. also: i ist 0, führe die Schleife aus solange i kleiner als 8, erhöhe i nach jedem Durchlauf um 1.

    In Kombination mit dem EventListener:



    Nach dem Klick
    Jetzt sind drei Dinge interessant:

    • Welcher Button wurde geklickt?
    • Welches Input Feld gehört dazu?
    • Was soll passieren?

    Hier kommt das veränderte name-Attribut der Buttons ins Spiel, dort sind alle Informationen enthalten:


    Code
    anzahl_rotwein1 - increase
       |                |
    Element           Aktion


    Vor dem Bindestrich steht das Input Element, dahinter die Aktion. Diese beiden Informationen müssen nun extrahiert werden, dazu wird erst das Element benötigt:


    JavaScript
    buttons[i].addEventListener("click", function (e) {
        var target = e.target;
    });


    In der Konsole geprüft enthält die target-Variable nun nach dem Klicken (z. B.):


    Code
    <input type="button" value="+" name="anzahl_weisswein1-increase" class="action_button">


    Als nächstes das name-Attribut auslesen:


    JavaScript
    buttons[i].addEventListener("click", function (e) {
        var target = e.target;
        var name = target.getAttribute("name");
    });


    Die Konsole meldet:


    Code
    anzahl_weisswein1-increase


    Als nächstes muss dieser String (Zeichenkette) aufgeteilt werden. Dafür gibt es in Javascript die split()-Funktion:


    JavaScript
    buttons[i].addEventListener("click", function (e) {
        var target = e.target;
        var name = target.getAttribute("name");
        var info = name.split("-");
    });


    Die Konsole zum Inhalt von "info":


    JavaScript
    Array [ 
        "anzahl_weisswein1", 
        "increase" 
    ]


    Jetzt kann das betroffene Input Element selektiert werden:


    JavaScript
    var input_element = document.getElementsByName(info[0])[0];


    Da ein Array zurückgegeben wird (siehe weiter oben), wird am Ende noch das 0-te Element ausgewählt. Es wäre auch Möglich statt dem name-Tag mit ID's zu arbeiten, da der name-Tag in einem Input Feld aber sowieso nötig ist, ist diese Lösung sogar einfacher (wenn man sie verstanden hat).


    Mit dem von Javascript zur Verfügung gestellten .value-Attribut lässt sich das Input Feld nun auslesen und bearbeiten, vorher wird entschieden ob hoch oder herunter gezählt wird:


    JavaScript
    if(info[1] == "increase")
    {
        input_element.value = parseInt(input_element.value) + 1;
    }
    else
    {
        input_element.value = parseInt(input_element.value) - 1;
    }


    Achtung! Der value-Wert vom Input Feld gibt einen String zurück, daher erst mittels parseInt() in einen Integer umwandeln und dann damit rechnen.


    Weniger als 0 Einträge im Warenkorb machen keinen Sinn, daher einfach eine kurze Überprüfung mit einbauen:



    Und noch ein mal der ganze Javascript Code:



    Am Anfang sicher viele verwirrende Faktoren aber wenn Fragen offen sind bitte immer raus damit.


    Die Zeilen 11-14 lassen sich übrigens zusammenfassen, so müssen nicht 4 Variablen zugewiesen werden (der Garbage-Collector wird es danken):


    JavaScript: 11
    var info = e.target.getAttribute("name").split("-");
    var input_element = document.getElementsByName(info[0])[0];


    Ich habe jetzt wirklich viel geschrieben, ich wusste nicht wie viel Grundwissen du besitzt. Wie bereits erwähnt: Wenn du irgendwas nicht verstehen solltest scheue dich nicht nachzufragen.


    Bei dem Code handelt es sich noch sehr um "Basics", man kann noch deutlich mehr Dynamik und Funktionalität da reinbringen.

  • Guten Abend liebe(r) Basi,


    vielen vielen Dank für deine ausführliche und interessante Antwort. Du hast dir wirklich sehr viel Mühe gegeben, um mir das Ganze verständlich zu erklären. Vor allen Dingen: Vielen Dank, dass du dir so viel Zeit für deine Antwort genommen hast. Ich freue mich wirklich sehr über deine Unterstützung!

  • Keine Ursache, schließlich hast du dir bei der Problembeschreibung ja auch Mühe gegeben. Außerdem habe ich dich (scheinbar richtig) so eingeschätzt, dass du gut damit klar kommst und es gerne annimmst. Sollten noch Schwierigkeiten auftauchen immer her damit :)

  • Liebe(r) Basi,


    ich freue mich wirklich riesig über deine Unterstützung. Ohne dich, hätte ich das sicher nicht hinbekommen. EventListener und Get-Methoden haben wir während des Kurses nicht behandelt.
    Ich habe tatsächlich noch eine Frage zum Bestellvorgang und würde mich über deine erneute Hilfe und deinen erneuten Rat sehr freuen.


    Zum Problem:
    Der Warenkorb ist einer von drei Schritten des Bestellvorgangs. Der erste Schritt ist ein Formular, welches die Kundendaten bzw. Lieferdaten abfragt und die ordnungsgemäße Eingabe der Daten überprüft. Der zweite Schritt ist der aktuelle Warenkorb, bei dessen Erstellung du mir so viel geholfen hast. Der dritte Schritt ist die Auswahl der Zahlungsart und die anschließende Übermittlung sämtlicher Formulardaten aus allen drei Schritten an eine E-Mail-Adresse. Während des Bestellvorgangs soll man innerhalb dieser drei Schritte vor und zurück navigieren können.


    Jetzt kommen meine Frag hierzu:
    Verbleibt die aktuelle Mengenauswahl des Warenkorbes im Zwischenspeicher oder würde dieser Zwischenspeicher und kann beim Abschließen des Bestellvorgangs benutzt werden oder wird beim Vor-und Zurückspringen zurückgesetzt werden?


    Zum zweiten Problem:
    Momentan habe ich die drei Schritte des Bestellvorgangs in einzelnen Dateien geschrieben. Geplant hatte ich, über einen Hyperlink zwischen den drei Teilen zu Navigieren. Ich habe mir diese drei Teile der Webseite also als eine neu geladenen Seite vorgestellt.


    Jetzt kommen meine Frage hierzu:
    Wie schätzt du dieses Vorgehen ein? Ist dieser Vorgang überhaupt empfehleneswert? Wäre hier z.B. die Verwendung einer "Group Box" eventuell besser geeignet?


    Über deine Meinung hierzu würde ich mich sehr freuen.

  • Hei!


    Beides ist theoretisch möglich. Wenn du das Formular über mehrere Dateien verteilst, brauchst du wieder PHP. In dem Fall musst du nämlich mit einer Session arbeiten. Sessions sind PHP Variablen, die auch beim wechsel der Unterseiten verfügbar bleiben. So löst man zum Beispiel Logins (daher auch der Begriff Login-Session).


    Ich würde der Einfachheit halber mit einer Seite arbeiten. Die verschiedenen Schritte kannst du dann in DIV Elemente packen, wobei du die gerade nicht relevanten Teile des Formulars ausblendest.


    Der HTML Aufbau könnte zum Beispiel so aussehen:



    Dann werden über CSS die Container bis auf den ersten ausgeblendet:


    CSS
    div.step-container {
        display: none;
    }
    
    
    
    
    div#step1 {
        display: block;
    }


    Es wird jetzt nur der erste Container angezeigt.


    Auffgefallen sind bestimmt die neuen Attribute der Buttons:


    HTML
    <button class="step-navigation-button" data-target="1">Weiter</button>


    In den data-* Attributen kann man für den Benutzer nicht relevante Daten speichern, also zum Beispiel Werte, die wichtig für eine Javascript Funktion sind. Der Aufbau ist immer der selbe, man beginnt mit data- und ist dann kreativ. In diesem Fall wählte ich data-target, weil der Wert die Nummer des Ziel-Containers beinhaltet. ALles zum data- Attribut hier.
    Auslesen kann man wie folgt:


    JavaScript
    var element = document.getElement...;
    var data    = element.dataset.target; // dataset.[alles hinter "data-"]


    Jetzt müssen nur noch die 4 Buttons eingelesen und mit EventListenern versehen werden. Außerdem müssen die (in diesem Fall 3) Container eingelesen werden.



    Zeile 7 könnte neu sein. Die Variable e enthält Event-relevante Daten (definiert in Zeile 6). Mittels preventDefault() wird das Standardverhalten des Browsers gestoppt. Wenn man dies also zum Beispiel auf einen a-Tag anwendet, wird die Funktionalität komplett aufgehoben, beim Klick wird nichts passieren.
    Manche Browser laden bei Buttons ohne value-Atribut die Seite neu, was das Formular leeren könnte.


    Anmerkung: Es ließe sich selbstverständlich statt data- auch einfach value verwenden, aber wieso nicht mal zwei neue Dinge lernen? ;) Außerdem ist das auch eine Sache von Geschmack. Ich habe lange Zeit Windows Apps programmiert, neben C# auch mit HTML und Javascript, da gewöhnt man sich die data-Attribute an, die sind extrem wertvoll.


    Jetzt bleibt nur noch das Auslesen des data-Tags und das entsprechende Anzeigen und Verbergen der betroffenen Elemente, einfach in die Schleife einfügen:



    Hier übrigens auch wieder Stil-Frage. Folgt nach einee if oder else Abfrage nur ein Befehl, kann man sich die { ... } (Befehlsblock) sparen, hilft bei Übersicht.


    Das onload Eventnicht vergessen und dann einfach mal ausprobieren:


Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!