Как определяется кнопка отправки по умолчанию в HTML-форме?

Если форма отправлена, но не какой-либо конкретной кнопкой, например

  • при нажатии Enter
  • используя HTMLFormElement.submit() в JS

как браузер должен определить, какую из нескольких кнопок отправки, если таковые имеются, использовать в качестве нажатой?

это важно на двух уровнях:

  • вызов onclick обработчик событий, прикрепленные к кнопке submit
  • данные, отправленные обратно в интернет сервер

мои эксперименты показали, что:

  • при нажатии Enter, Firefox, Opera и Safari используйте первую кнопку отправки в форме
  • при нажатии Enter, IE использует либо первую кнопку отправки, либо вообще нет в зависимости от условий, которые я не смог выяснить
  • все эти браузеры не используют вообще для отправки JS

что делает стандарт сказать?

Если это поможет, вот мой тестовый код (PHP относится только к моему методу тестирования, а не к самому моему вопросу)

<!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>

14 ответов


Если вы отправляете форму через JavaScript (т. е. formElement.submit() или что-нибудь эквивалентное), то нет кнопки отправки считаются успешными, и ни одно из их значений не включается в отправленные данные. (Обратите внимание, что если вы отправляете форму с помощью submitElement.click() тогда submit, на который у вас была ссылка, считается активным; это действительно не подпадает под компетенцию вашего вопроса, так как здесь кнопка отправки однозначна, но я думал, что включу ее для людей, которые читают первая часть и интересно, как сделать кнопку отправки успешной с помощью отправки формы JS. Конечно, обработчики формы onsubmit все равно будут работать таким образом, тогда как они не будут через form.submit() так это другой коленкор...)

Если форма представляется, нажав Enter в то время как в поле без textarea, то это на самом деле до агента пользователя, чтобы решить, что он хочет здесь. The технические характеристики ничего не говорите о отправке формы с помощью клавиши enter в текстовой записи поле (если вы вкладываете кнопку и активируете ее, используя пробел или что-то еще, то нет проблем, поскольку эта конкретная кнопка отправки однозначно используется). Все, что он говорит, что форма должна быть отправлена, когда кнопка отправки активирована, это даже не требование, что нажатие enter, например, текстовый ввод отправит форму.

Я считаю, что Internet Explorer выбирает кнопку отправки, которая появляется первой в источнике; у меня такое чувство, что Firefox и Opera выбирают кнопку с самый низкий tabindex, возвращаясь к первому определенному, если ничего больше не определено. Есть также некоторые осложнения относительно того, имеют ли отправители атрибут значения по умолчанию IIRC.

дело в том, что нет определенного стандарта для того, что здесь происходит, и это полностью по прихоти браузера - так что, насколько это возможно, что бы вы ни делали, старайтесь не полагаться на какое-либо конкретное поведение. Если вам действительно нужно знать, вы, вероятно, можете узнать поведение различные версии браузера, но когда я исследовал это некоторое время назад, были некоторые довольно запутанные условия (которые, конечно, могут измениться с новыми версиями браузера), и я бы посоветовал вам избегать этого, если это возможно!


Andrezj в значительной степени получил его прибил... но вот простое кросс-браузерное решение.

возьмите такую форму:

<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>

и рефакторинг этого:

<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>

поскольку спецификация W3C указывает, что несколько кнопок отправки действительны, но опускает руководство о том, как пользовательский агент должен обрабатывать их, производители браузеров остаются для реализации, как они считают нужным. Я обнаружил, что они либо отправят первую кнопку отправки в форме, либо отправят следующую отправку кнопка после поля формы, которое в настоящее время имеет фокус.

к сожалению, просто добавив стиль дисплей: нет; не будет работать, потому что спецификация W3C указывает, что любой скрытый элемент должен быть исключен из взаимодействия с пользователем. Так что спрячьте его на виду!

выше приведен пример решения, которое я в конечном итоге ввел в производство. Нажатие клавиши enter запускает отправку формы по умолчанию-это поведение, как и ожидалось, даже если другие значения не по умолчанию присутствует и предшествует кнопке отправки по умолчанию в DOM. Бонус за взаимодействие мыши/клавиатуры с явными пользовательскими входами, избегая обработчиков javascript.

Примечание: вкладка через форму не будет отображать фокус для любого визуального элемента, но все равно вызовет невидимую кнопку для выбора. Чтобы избежать этой проблемы, просто установите атрибуты tabindex соответственно и опустите атрибут tabindex на невидимой кнопке отправки. Хотя это может показаться неуместным, чтобы продвигать эти стили !важно, они должны предотвратите любые рамки или существующие стили кнопок от вмешательства в это исправление. Кроме того, эти встроенные стили определенно плохая форма, но мы доказываем концепции здесь... не писать производственный код.


HTML 4 не делает его явным. Текущий рабочий проект HTML5 указывает, что первая кнопка "Отправить" должна быть по умолчанию:

A form кнопка элемента по умолчанию первый отправить кнопку in дерево чей владелец форма это form элемент.

Если агент пользователя поддерживает разрешение пользователю отправить форму неявно (например, на некоторых платформах ввод в то время как текстовое поле фокусируется неявно отправляет форму), то это делается для формы, которая по умолчанию определен поведение активации!--4--> должен вызвать агент пользователя выполнить шаги активации синтетического щелчка на что по умолчанию.


Я думаю, что этот пост поможет, если кто-то хочет сделать это с помощью jQuery:

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

основное решение:

$(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;
    }
    });
});

и еще мне понравилось:

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;
}
});
}); 

У меня была форма с 11 кнопками отправки, и она всегда будет использовать первую кнопку отправки, когда пользователь нажмет enter. Я читал в другом месте, что это не хорошая идея (плохая практика) иметь более одной кнопки отправки в форме, и лучший способ сделать это-иметь кнопку, которую вы хотите по умолчанию, как единственную кнопку отправки в форме. Другие кнопки должны быть сделаны в "TYPE=BUTTON" и добавлено событие onClick, которое вызывает вашу собственную процедуру отправки в Javascript. Что-то вроде этого :-

<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();">

здесь button3 является значением по умолчанию, и хотя вы программно отправляете форму с другими кнопками, процедура mjsubmit проверяет их. HTH.


теперь это можно решить с помощью flexbox:

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 */
}

объяснение
Используя flex box, мы можем изменить порядок элементов в контейнере, который использует display: flex также используя правило CSS:flex-direction: row-reverse. Это не требует CSS или скрытых элементов. Для старых браузеров, которые не поддерживают flexbox, они по-прежнему получают работоспособное решение, но элементы будут не быть перевернутым.

демо
http://codepen.io/Godwin/pen/rLVKjm


я боролся с тем же вопросом, так как у меня была кнопка отправки в середине, с которой перенаправлено отправить на другую страницу, например:

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

когда пользователь нажал клавишу enter, эта кнопка была нажата вместо другой кнопки отправки.

поэтому я сделал несколько примитивных тестов, создав из с несколькими кнопками отправки и различными параметрами видимости и предупреждением о событии onclick, какая кнопка была нажата: https://jsfiddle.net/aqfy51om/1/

браузеры и ОС, которые я использовал для тестирования:

WINDOWS

  • Google Chrome 43 (давайте google: D)
  • Mozilla Firefox 38
  • Internet Explorer 11
  • Опера 30.0

OSX

  • Google Chrome 43
  • Safari 7.1.6

большинство из этих браузеров нажал самую первую кнопку, несмотря на примененные параметры видимости exept IE и Safari который нажал третью кнопку, которая" видна "внутри" скрытого " контейнера:

<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>

Итак, мое предложение, которое я собираюсь использовать сам:

если у вас есть несколько кнопок отправки с разным значением, включите кнопку отправки с действием по умолчанию в начале формы, которое:

  1. полностью видимый
  2. завернутый в контейнер с style="width: 0; height: 0; overflow: hidden;"

редактировать Другим вариантом может быть смещение кнопки (все еще в начале from) style="position: absolute; left: -9999px; top: -9999px;", просто попробовал в IE - работает , но я понятия не имею, что еще он может испортить, например печати..


из комментариев:

следствием является то, что, если у вас есть несколько форм представления же сценарий, вы не можете положиться на submit кнопки, чтобы отличить их.

Я удалить <input type="hidden" value="form_name" /> в каждой форме.

при отправке с помощью javascript: добавьте события отправки в формы, а не нажмите события на их кнопки. Пользователи Saavy не очень часто прикасаются к своей мыши.


когда у вас есть несколько кнопок отправки в одной форме, и пользователь нажимает клавишу ENTER для отправки формы из текстового поля, этот код переопределяет функциональность по умолчанию, вызывая событие отправки в форме из события нажатия клавиши. Вот этот код:

$('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;

});

странно, что первая кнопка Enter всегда идет к первой кнопке независимо от того, виден или нет, например, с помощью jquery show/hide(). Добавление атрибута .attr('disabled', 'disabled') предотвратить получение введите кнопку Отправить. Это проблема, например, при настройке Вставить / Изменить+Удалить видимость кнопки в диалогах записи. Я нашел менее hackish и простое размещение редактировать перед вставить

<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>

и использовать javascript код:

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

мой рецепт:

<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>

он отправит скрытое поле по умолчанию, если ни одна из кнопок не будет "нажата".

если они нажаты, у них есть предпочтение, и это значение передается.


другое решение, которое я использовал, - это просто иметь одну кнопку в форме и подделать другие кнопки.

вот пример:

<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>

затем я стилизую элементы span, чтобы они выглядели как кнопка. Прослушиватель JS наблюдает за промежутком и выполняет требуемую операцию после нажатия.

Не обязательно верно для всех ситуаций, но по крайней мере это довольно легко сделать.


с HTML 4 spec:

Если форма содержит более одной кнопки отправки, активируется только кнопки "Отправить" является успешной.

Это означает, что, учитывая более 1 кнопки отправки и ни один не активирован (нажат), ни один не должен быть успешным.

и я бы сказал, что это имеет смысл: Представьте себе огромную форму с несколькими кнопками submit. В верхней части есть кнопка"Удалить эту запись", затем следует много входов и на внизу есть кнопка"обновить эту запись". Пользователь, нажимая enter в поле внизу формы, никогда не заподозрит, что он неявно нажимает "удалить эту запись" сверху.

поэтому я думаю, что не стоит использовать первую или любую другую кнопку, которую пользователь не определяет (нажмите). Тем не менее, браузеры делают это естественно.


EDIT: Извините, при написании этого ответа я думал о кнопках отправки в общем смысле. Ответ ниже не о нескольких type="submit" кнопки, так как он оставляет только один type="submit" и измените другой на type="button". Я оставляю ответ здесь в качестве ссылки в случае, если помогает кто-то, кто может изменить type в виде:

чтобы определить, какая кнопка нажата при нажатии enter, вы можете пометить ее с помощью type="submit", а другие кнопки помечают их type="button". Например:

<input type="button" value="Cancel" />
<input type="submit" value="Submit" />