wake-up-neo.com

Wie wird die Standardschaltfläche zum Senden in einem HTML-Formular festgelegt?

Wenn ein Formular gesendet wird, aber nicht über eine bestimmte Schaltfläche, z

  • durch Drücken Enter
  • mit HTMLFormElement.submit() in JS

wie soll ein Browser bestimmen, welche der mehreren Sende-Schaltflächen, falls vorhanden, als diejenige verwendet werden soll, die gedrückt wird?

Dies ist auf zwei Ebenen von Bedeutung:

  • aufrufen eines onclick -Ereignishandlers, der an eine Senden-Schaltfläche angehängt ist
  • die an den Webserver zurückgesendeten Daten

Meine bisherigen Experimente haben gezeigt, dass:

  • beim drücken Enter, Firefox, Opera und Safari verwenden die erste Senden-Schaltfläche im Formular
  • beim drücken Enter, IE verwendet entweder den ersten Submit-Button oder gar keinen, abhängig von den Bedingungen, die ich nicht herausfinden konnte
  • alle diese Browser verwenden überhaupt keine für eine JS-Übermittlung

Was sagt der Standard?

Wenn es helfen würde, hier ist mein Testcode (der PHP ist nur für meine Testmethode relevant, nicht für meine Frage selbst)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Test</title>
</head>

<body>

<h1>Get</h1>
<dl>
<?php foreach ($_GET as $k => $v) echo "<dt>$k</dt><dd>$v</dd>"; ?>
</dl>

<h1>Post</h1>
<dl>
<?php foreach ($_POST as $k => $v) echo "<dt>$k</dt><dd>$v</dd>"; ?>
</dl>

<form name="theForm" method="<?php echo isset($_GET['method']) ? $_GET['method'] : 'get'; ?>" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>">
    <input type="text" name="method" />
    <input type="submit" name="action" value="Button 1" onclick="alert('Button 1'); return true" />
    <input type="text" name="stuff" />
    <input type="submit" name="action" value="Button 2" onclick="alert('Button 2'); return true" />
    <input type="button" value="submit" onclick="document.theForm.submit();" />
</form>

</body></html>
199
Stewart

Wenn Sie das Formular über Javascript (dh formElement.submit() oder eine gleichwertige Option) senden, wird keine der Senden-Schaltflächen als erfolgreich angesehen und keine ihrer Werte sind in den übermittelten Daten enthalten. (Beachten Sie, dass, wenn Sie das Formular mit submitElement.click() senden, die Übermittlung, auf die Sie einen Verweis hatten, als aktiv betrachtet wird. Dies fällt nicht wirklich in den Aufgabenbereich Ihrer Frage, da hier die Übermittlungsschaltfläche jedoch eindeutig ist Ich dachte, ich würde es für Leute einschließen, die den ersten Teil lesen und sich fragen, wie eine Übermittlungsschaltfläche über die Übermittlung von JS-Formularen erfolgreich gemacht werden kann. Natürlich werden die Onsubmit-Handler des Formulars immer noch auf diese Weise ausgelöst, während sie nicht über form.submit() das ist also ein weiterer Kessel mit Fisch ...)

Wenn das Formular gesendet wird, indem Sie die Eingabetaste drücken, während Sie sich in einem Nicht-Textfeld befinden, kann der Benutzeragent selbst entscheiden, was hier gewünscht wird. Das specs sagt nichts über das Absenden eines Formulars mit der Eingabetaste in einem Texteingabefeld aus (wenn Sie auf eine Schaltfläche tippen und sie mit Leerzeichen oder was auch immer aktivieren, dann gibt es kein Problem als solches wird eindeutig verwendet). Es heißt nur, dass ein Formular gesendet werden muss, wenn eine Senden-Schaltfläche aktiviert ist. Es ist nicht einmal eine Anforderung, dass Eingabetaste in z. Bei einer Texteingabe wird das Formular gesendet.

Ich glaube, dass Internet Explorer die Schaltfläche zum Senden auswählt, die zuerst in der Quelle angezeigt wird. Ich habe das Gefühl, dass Firefox und Opera) die Schaltfläche mit dem niedrigsten Tabulatorindex auswählen und auf den ersten zurückgreifen, wenn nichts anderes definiert ist. Es gibt auch einige Komplikationen, ob die Übermittlungen einen Nicht-Standardwert haben Wertattribut IIRC.

Der Punkt, den Sie außer Acht lassen sollten, ist, dass es keinen definierten Standard für das gibt, was hier passiert, und dass dies ganz nach Belieben des Browsers geschieht. Versuchen Sie, sich so weit wie möglich auf ein bestimmtes Verhalten zu verlassen. Wenn Sie wirklich wissen müssen, können Sie wahrscheinlich das Verhalten der verschiedenen Browserversionen herausfinden, aber als ich dies vor einiger Zeit untersuchte, gab es einige recht verworrene Bedingungen (die sich natürlich mit neuen Browserversionen ändern können) und ich würde raten Sie vermeiden es, wenn möglich!

109
Andrzej Doyle

Andrezj hat es ziemlich genau verstanden ... aber hier ist eine einfache browserübergreifende Lösung.

Nehmen Sie eine Form wie diese an:

<form>
    <input/>
    <button type="submit" value="some non-default action"/>
    <button type="submit" value="another non-default action"/>
    <button type="submit" value="yet another non-default action"/>

    <button type="submit" value="default action"/>
</form>

und Refactor dazu:

<form>
    <input/>

    <button style="overflow: visible !important; height: 0 !important; width: 0 !important; margin: 0 !important; border: 0 !important; padding: 0 !important; display: block !important;" type="submit" value="default action"/>

    <button type="submit" value="some non-default action"/>
    <button type="submit" value="another non-default action"/>
    <button type="submit" value="yet another non-default action"/>
    <button type="submit" value="still another non-default action"/>

    <button type="submit" value="default action"/>
</form>

Da die W3C-Spezifikation angibt, dass mehrere Übermittlungsschaltflächen gültig sind, jedoch keine Anleitung dazu enthält, wie der Benutzeragent mit ihnen umgehen soll, müssen die Browserhersteller diese nach eigenem Ermessen implementieren. Ich habe festgestellt, dass sie entweder die erste Übermittlungsschaltfläche im Formular übermitteln oder die nächste Übermittlungsschaltfläche nach dem Formularfeld, das derzeit den Fokus hat, übermitteln.

Leider funktioniert es nicht, einfach einen Stil von display: none; hinzuzufügen, da die W3C-Spezifikation angibt, dass verborgene Elemente von Benutzerinteraktionen ausgeschlossen werden sollten. Verstecken Sie es stattdessen in der Öffentlichkeit!

Oben ist ein Beispiel für die Lösung, die ich letztendlich in Produktion genommen habe. Wenn Sie die Eingabetaste drücken, wird die Übermittlung des Standardformulars wie erwartet ausgeführt, auch wenn andere, nicht standardmäßige Werte vorhanden sind und der Standard-Übermittlungsschaltfläche im DOM vorangehen. Bonus für Maus/Tastatur-Interaktion mit expliziten Benutzereingaben unter Vermeidung von Javascript-Handlern.

Hinweis: Wenn Sie durch das Formular tippen, wird für kein visuelles Element der Fokus angezeigt, und dennoch wird die unsichtbare Schaltfläche ausgewählt. Um dieses Problem zu vermeiden, legen Sie einfach die tabindex-Attribute entsprechend fest und lassen Sie ein tabindex-Attribut auf der unsichtbaren Senden-Schaltfläche weg. Obwohl es unangebracht erscheint, diese Stile für! Important zu promoten, sollten sie sollte verhindern, dass Frameworks oder vorhandene Schaltflächenstile diese Korrektur beeinträchtigen. Auch diese Inline-Stile sind definitiv schlecht in der Form, aber wir beweisen hier Konzepte ... ohne Produktionscode zu schreiben.

60
James

HTML 4 macht es nicht explizit. Der aktuelle HTML5-Arbeitsentwurf gibt an, dass die erste Senden-Schaltfläche die Standardschaltfläche sein muss :

EIN form Die Standardschaltfläche des Elements ist die erste Senden-Schaltfläche in Baumreihenfolge deren Formulareigentümer ist das form Element.

Wenn der Benutzeragent die implizite Übermittlung eines Formulars durch den Benutzer unterstützt (z. B. bei einigen Plattformen, bei denen die Eingabetaste gedrückt wird, während ein Textfeld fokussiert ist, wird das Formular implizit übermittelt), gilt dies für ein Formular, dessen Standardschaltfläche) hat ein definiertes Aktivierungsverhalten muss den Benutzeragenten veranlassen synthetische Klickaktivierungsschritte auszuführen darauf Standardschaltfläche .

58
Quentin

Ich denke, dieser Beitrag würde helfen, wenn jemand es mit jQuery machen möchte:

http://greatwebguy.com/programming/dom/default-html-button-submit-on-enter-with-jquery/

Die Grundlösung ist:

$(function() {
    $("form input").keypress(function (e) {
    if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
        $('input[type=submit].default').click();
        return false;
    } else {
        return true;
    }
    });
});

und eine andere, die mir gefiel, war:

jQuery(document).ready(function() {
$("form input, form select").live('keypress', function (e) {
if ($(this).parents('form').find('button[type=submit].default, input[type=submit].default').length <= 0)
return true;

if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
$(this).parents('form').find('button[type=submit].default, input[type=submit].default').click();
return false;
} else {
return true;
}
});
}); 
16

Ich hatte ein Formular mit 11 Senden-Schaltflächen und es wurde immer die erste Senden-Schaltfläche verwendet, wenn der Benutzer die Eingabetaste drückte. Ich habe an anderer Stelle gelesen, dass es keine gute Idee (schlechte Praxis) ist, mehr als eine Senden-Schaltfläche in einem Formular zu haben. Der beste Weg, dies zu tun, ist, die gewünschte Schaltfläche als Standardschaltfläche als einzige Senden-Schaltfläche im Formular festzulegen. Die anderen Schaltflächen sollten zu "TYPE = BUTTON" gemacht und ein onClick-Ereignis hinzugefügt werden, das Ihre eigene Submit-Routine in Javascript aufruft. Etwas wie das :-

<SCRIPT Language="JavaScript">
function validform()
{
  // do whatever you need to validate the form, and return true or false accordingly
}

function mjsubmit()
{
  if (validform()) { document.form1.submit(); return true;}
  return false;
}
</SCRIPT>
<INPUT TYPE=BUTTON NAME="button1" VALUE="button1" onClick="document.form1.submitvalue='button1'; return mjsubmit();">
<INPUT TYPE=BUTTON NAME="button2" VALUE="button2" onClick="document.form1.submitvalue='button2'; return mjsubmit();">
<INPUT TYPE=SUBMIT NAME="button3" VALUE="button3" onClick="document.form1.submitvalue='button3'; return validform();">
<INPUT TYPE=BUTTON NAME="button4" VALUE="button4" onClick="document.form1.submitvalue='button4'; return mjsubmit();">

Hier ist button3 die Standardeinstellung, und obwohl Sie das Formular programmgesteuert mit den anderen Schaltflächen senden, validiert die Routine mjsubmit sie. HTH.

6
graphic

Dies kann nun mit flexbox gelöst werden:

[~ # ~] html [~ # ~]

<form>
    <h1>My Form</h1>
    <label for="text">Input:</label>
    <input type="text" name="text" id="text"/>

    <!-- Put the elements in reverse order -->
    <div class="form-actions">
        <button>Ok</button> <!-- our default action is first -->
        <button>Cancel</button>
    </div>
</form>

[~ # ~] CSS [~ # ~]

.form-actions {
    display: flex;
    flex-direction: row-reverse; /* reverse the elements inside */
}

Erklärung
Mit flex box können wir die Reihenfolge der Elemente in einem Container umkehren, in dem display: flex auch mit der CSS-Regel: flex-direction: row-reverse. Dies erfordert kein CSS oder versteckte Elemente. Ältere Browser, die Flexbox nicht unterstützen, erhalten weiterhin eine funktionsfähige Lösung, die Elemente werden jedoch nicht umgekehrt.

Demo
http://codepen.io/Godwin/pen/rLVKjm

5
Godwin

Ich hatte mit der gleichen Frage zu kämpfen, da ich einen Submit-Button in der Mitte des umgeleiteten Submit-Buttons zu einer anderen Seite hatte:

<button type="submit" onclick="this.form.action = '#another_page'">More</button>

Wenn der Benutzer die Eingabetaste drückte, wurde auf diese Schaltfläche anstelle einer anderen Senden-Schaltfläche geklickt.

Also habe ich einige primitive Tests durchgeführt, indem ich ein From mit mehreren Submit-Schaltflächen und verschiedenen Sichtbarkeitsoptionen erstellt und auf ein Ereignis geklickt habe: https://jsfiddle.net/aqfy51om/1/

Browser und Betriebssysteme, die ich zum Testen verwendet habe:

[~ # ~] windows [~ # ~]

  • Google Chrome 43 (c'mon google: D)
  • Mozilla Firefox 38
  • Internet Explorer 11
  • Opera 30.0

[~ # ~] osx [~ # ~]

  • Google Chrome 43
  • Safari 7.1.6

Die meisten dieser Browser haben auf die erste Schaltfläche geklickt, obwohl die Sichtbarkeitsoptionen angewendet wurden , mit Ausnahme von IE und Safari , die auf die dritte Schaltfläche geklickt haben. Das ist "sichtbar" in "versteckten" Containern:

<div style="width: 0; height: 0; overflow: hidden;">
    <button type="submit" class="btn btn-default" onclick="alert('Hidden submit button #3 was clicked');">Hidden submit button #3</button>
</div>

Also mein Vorschlag, den ich selbst verwenden werde, ist:

Wenn Ihr Formular über mehrere Übermittlungsschaltflächen mit unterschiedlicher Bedeutung verfügt, fügen Sie die Übermittlungsschaltfläche mit der Standardaktion am Anfang des Formulars ein.

  1. Voll sichtbar
  2. Eingewickelt in einen Behälter mit style="width: 0; height: 0; overflow: hidden;"

[~ # ~] edit [~ # ~] Eine andere Möglichkeit könnte sein, die Schaltfläche zu verschieben (noch am Anfang des von) style="position: absolute; left: -9999px; top: -9999px;", habe es gerade in IE - gearbeitet, aber ich habe keine Ahnung, was es sonst vermasseln kann, zum Beispiel Drucken ..

2
Kristian

Wenn Sie mehrere Senden-Schaltflächen in einem einzelnen Formular haben und ein Benutzer die EINGABETASTE drückt, um das Formular aus einem Textfeld zu senden, überschreibt dieser Code die Standardfunktionalität, indem er das Senden-Ereignis für das Formular aus dem Tastendruckereignis aufruft. Hier ist der Code:

$('form input').keypress(function(e){

    if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)){ $(e.target).closest('form').submit(); return false; }
    else return true;

});
1
axiom82

Aus Ihren Kommentaren:

Wenn Sie mehrere Formulare an dasselbe Skript senden, können Sie sich nicht darauf verlassen, dass die Schaltflächen zum Senden diese unterscheiden.

Ich lasse ein <input type="hidden" value="form_name" /> in jedes Formular.

Bei Übermittlung mit Javascript: Fügen Sie Übermittlungsereignisse zu Formularen hinzu, und klicken Sie nicht auf Ereignisse zu deren Schaltflächen. Saavy-Benutzer berühren ihre Maus nicht oft.

1
Ryan Florence

Seltsam, dass der erste Knopf Enter immer zum ersten Knopf geht, unabhängig davon, ob er sichtbar ist oder nicht, z. mit jquery show/hide(). Das Hinzufügen des Attributs .attr('disabled', 'disabled') verhindert das vollständige Empfangen der Eingabetaste. Dies ist beispielsweise ein Problem beim Anpassen von Einfügen/Bearbeiten + Löschen Sichtbarkeit von Schaltflächen in Datensatzdialogen. Ich fand weniger hackisch und einfache Platzierung Bearbeiten vor Einfügen

<button type="submit" name="action" value="update">Update</button>
<button type="submit" name="action" value="insert">Insert</button>
<button type="submit" name="action" value="delete">Delete</button>

und benutze Javascript Code:

$("#formId button[type='submit'][name='action'][value!='insert']").hide().attr('disabled', 'disabled');
$("#formId button[type='submit'][name='action'][value='insert']").show().removeAttr('disabled');
1
TMa

Aus der HTML 4 Spezifikation :

Wenn ein Formular mehr als eine Senden-Schaltfläche enthält, ist nur die aktivierte Senden-Schaltfläche erfolgreich.

Dies bedeutet, dass bei mehr als einem Senden-Button und keinem aktivierten (angeklickten), keiner erfolgreich sein sollte.

Und ich würde argumentieren, dass dies sinnvoll ist: Stellen Sie sich ein riesiges Formular mit mehreren Submit-Buttons vor. Oben gibt es einen "Diesen Datensatz löschen" -Button, danach folgen viele Eingaben und unten gibt es einen "Diesen Datensatz aktualisieren" -Button. Ein Benutzer, der in einem Feld am unteren Rand des Formulars die Eingabetaste drückt, würde niemals den Verdacht haben, dass er implizit die Schaltfläche "Diesen Datensatz löschen" von oben drückt.

Daher halte ich es für keine gute Idee, den ersten oder einen anderen Knopf zu verwenden, den der Benutzer nicht definiert (klickt). Trotzdem machen es die Browser natürlich.

0
Christopher K.

mein Rezept:

<form>
<input type=hidden name=action value=login><!-- the magic! -->

<input type=text name=email>
<input type=text name=password>

<input type=submit name=action value=login>
<input type=submit name=action value="forgot password">
</form>

Es wird das standardmäßig ausgeblendete Feld gesendet, wenn keine der Schaltflächen angeklickt wird.

wenn sie angeklickt werden, haben sie Vorrang und ihr Wert wird übergeben.

0
gcb

Eine andere Lösung, die ich verwendet habe, besteht darin, nur eine Schaltfläche im Formular zu haben und die anderen Schaltflächen zu fälschen.

Hier ist ein Beispiel:

<form>
  <label for="amount">Amount of items</label>
  <input id="amount" type="text" name="amount" />
  <span id="checkStock" class="buttonish">Check stock</span>
  <button type="submit" name="action" value="order">Place order</button>
</form>

Anschließend gestalte ich die Span-Elemente so, dass sie wie eine Schaltfläche aussehen. Ein JS-Listener beobachtet die Spanne und führt die gewünschte Operation aus, sobald er darauf geklickt hat.

Nicht unbedingt für alle Situationen geeignet, aber zumindest ist das ziemlich einfach.

0