Aufgabenstellung / Zielsetzung

Üblicherweise reagieren alle Formulare auf Websites lt. Browser-Standard gleich, in dem diese beim Drücken der ENTER-Taste auf der Tastatur abgesendet werden. Beginnend mit dem Formular RM-Zuschnitte anfragen/blanko bestellen, sollte dieses Standardverhalten geändert werden, weil der Chef meint, dass das kein Benutzer im Internet so erwarten würde. Vermutlich rührt diese falsche Benutzererwartung daher, dass EXCEL-Benutzer mit Enter zur nächsten Zelle springen können. Deshalb wurde das Verhalten des o.g. Formular speziell für ENTER wie folgt verbogen :

  1. Zunächst sollte das Formular nicht mehr abgesendet werden bei ENTER
  2. Statt dessen sollte ENTER wie Tab funktionieren und bei jedem ENTER zum jeweils nächsten Feld springen.
  3. Welches Feld das nächste ist, weiss ein Formular bei Nutzung der TABULATOR-Taste, aber nicht bei ENTER. Deshalb muss dem Fomular speziell über das Feld-Attribut tabindex eine Reihenfolge mitgegeben werden.
  4. Nur die Felder (z.B. nur Inputfelder aber keine Radio-Buttons) sollen in der Tab-Reihenfolge angesprungen werden. Hier soll also eine Auswahlfreiheit bestehen.
  5. Für die erste ENTER-Eingabe soll bevorzugt ein Feld konfiguriert werden können, welches dann den Fokus erhält. Wenn kein solches Feld definiert wurde, soll das erste Feld in der TabIndex-Liste den Focus erhalten.
  6. Der Submit-Button soll erst wenn er selbst schon den Focus auf sich hat mit ENTER das Formular absenden.

 

Umsetzung im Detail

Für die Gesamte Aufgabenstellung wurde zur Umsetzung eine jQuery-Funktion erstellt, die mit dem betreffenden Fomular geladen wird.

zu 1. Formular bei ENTER nicht senden

Damit ein Web-Formular beim ENTER abgesendet wird, muss es eine input-Feld vom type submit geben (<input type="submit" />). Damit das Senden also nicht erfolgt, muss dieses Attribut aus dem input-Feld entfernt werden. Ersatzweise muss dieser Senden-Button natürlich wenigstens eine onClick-Ereignisbehandlung erhalten, bei dem z.B. eine JavaScript-Funktion ausgerführt wird. Dieses Script kann z.B. die Formular-Validierung vornehmen und bei korrekter Füllung das submit ausführen.

Zusätzlich wird in der Formular-Tag ein onsubmit-Ereignistrigger eingefügt, mit dem gleichen JS-Funktions-Aufruf wie das onClick im Senden-Button.

<form ... onsubmit="javascript:checkFormDimensions( this.id ); return false;" >

 

zu 2. bis 5. ENTER funktioniert wie Tab mit Feldwechsel

Zunächst versehen wir dazu jedes in die TabIndex-Liste aufzunehmende Input-Formular-Element mit einem Attribut tabindex. Das ist ein Standard-Formular-Attribut, welches alle Browser kennen. Hier wird ein Zahl übergeben die die Reihenfolge festlegt. Das muss keine fortlaufende Zahl sein, sondern kann auch Sprünge aufweisen. Und, nicht alle Formularfelder müssen so ein TabIndex-Attribut erhalten, sondern nur die, welche dann durch unser Script auch angesprungen werden sollen. Z.B. kann man sich auf reine Input-Felder vom type text beschränken.

Dann wurde eine JavaScript/jQuery-Funktion in components/com_virtuemart/themes/Marks/checkRMZFormDim_V02.js erstellt, die die ENTER-Behandlung vornimmt.
Sobald auf der Formularseite ENTER gedrückt wird (event.which == 13), dann werden per jQuery und dem Selector Attribut tabindex alle so ausgestatteten Formularfelder geholt ( $('*[tabindex]') ) und in $allTabindexedEl abgelegt. in currFucusedEl wird der TabIndex des Feldes gespeichert, welches aktuell den Focus hat.

Wenn kein Feld den Focus hat, dann ist der Index von currFocusedEl = -1. Für diesen Fall gibt es entweder ein per Class-Selector .firstTabIndex benanntes Feld, welches den Focus erhalten soll, oder es wird das erste Feld in der oben ermittelten Collection zum fokussierten Feld. Hat jedoch ein Feld aus der Collection den Focus, dann werden alle Felder der Collection mit each() durchlaufen, um festzustellen, welches den Focus hat und folglich welches das nächst Feld wäre. In allen drei Fällen wird die Referenz auf das nächste Feld in $next gespeichert um am Scriptende per .focus() und .select() den Focus zu erhalten.



zu 6. Absenden des Formulars mit ENTER wenn der Focus auf dem Senden-Button steht

Mit dieser kleinen Kompromisslösung kann die oben vorgenomme Verbiegung des Formularverhaltens bzgl. ENTER-Submit wieder etwas entschärft werden, in dem das Absenden des Formulars per ENTER doch möglich bleibt, wenn der Submit-Button schon aktuell den Fokus hat - und eben nur dann.

Dazu übergibt man dem Submit-Button eine ID (z.B. <input id="addToCartBtn" />), welche dann über jQuery gefunden werden kann. Wenn die ID des aktuell den Focus haltendenden Formularelementes (ermittelt mit event.target.id) dieser ID enspricht, dann wird jetzt das Formular versendet statt eine Tab-Funktion auszuführen.

Beachten: Text-Area-Formularfelder: Sollten sich bei Enter anders verhalten! hier ist ein Enter natürlich ein Zeilenumbruch und es sollte nicht mit einem Feldwechsel reagieren. Das wäre nervig. Dieser Fall wird in unserem Script derzeit nicht abgefangen/behandelt.

 

Hier nun das gesamte Scriptbeispiel:

;(function($) {
    $(document).on('keyup', function (event) {
        event.preventDefault();
        // console.log(event.which);
        if (event.which == 13) {
            $allTabindexedEl = $('*[tabindex]'); // Finde Formelemente mit tabindex
            currFocusedEl = $allTabindexedEl.index(event.target); // wenn eins aktuell den Focus hat, dann idx sonst -1
             console.log(currFocusedEl+'. von '+ $allTabindexedEl.length+' Elementen');

            if (currFocusedEl == -1) {
                // wenn nichts focusiert, dann erstes Element
                $firstTabIndex = $('.firstTabIndex');
                if ($firstTabIndex.length) {
                    $next = $firstTabIndex[0];
                } else {
                    $next = $allTabindexedEl[0];
                }
            } else {
                // wenn addToCartBtn schon Focus hat dann Fomuluar damit senden
                if (event.target.id == 'addToCartBtn') {
                    javascript:checkFormDimensions( event.target.form.id );
                    return false;
                } else {
                    // sonst das nächste auswählen
                    $allTabindexedEl.each(function(index) {
                        // console.log(index+': '+$(this).attr('id')+': '+$(this).attr('tabindex'));
                        if (index == currFocusedEl) {
                            $next = $allTabindexedEl[index + 1];
                            return false;
                        }
                    });
                }
            }
            $next.focus();
            $next.select();
        }
        return false;
    });
})(jQuery);