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

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

  • нажав Enter
  • с помощью HTMLFormElement.submit() в JS

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

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

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

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

  • при нажатии 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>

Ответ 1

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

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

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

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

Ответ 2

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 указывает, что несколько кнопок отправки действительны, но не дает указания относительно того, как пользовательский агент должен их обрабатывать, производители браузеров оставляют для реализации по своему усмотрению. Я обнаружил, что они либо отправят первую кнопку отправки в форме, либо отправят следующую кнопку отправки после поля формы, которое в настоящее время имеет фокус.

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

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

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

Ответ 3

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

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

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

Ответ 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;
}
});
}); 

Ответ 5

У меня была форма с 11 кнопками отправки на ней, и она всегда использовала бы первую кнопку отправки, когда пользователь нажал кнопку ввода. Я читал в другом месте, что не очень хорошая идея (плохая практика) иметь более одной кнопки отправки в форме, и лучший способ сделать это - использовать кнопку, которую вы хотите по умолчанию, в качестве единственной кнопки отправки в форме. Другие кнопки должны быть превращены в "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();">

Здесь кнопка3 по умолчанию, и хотя вы программно представляете форму с помощью других кнопок, процедура mjsubmit проверяет их. НТН.

Ответ 6

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

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

Когда пользователь нажал клавишу ввода, эта кнопка была нажата, а не другая кнопка отправки.

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

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

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

Большинство этих браузеров щелкнули самую первую кнопку, несмотря на то, что были применены параметры видимости за исключением 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>

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

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

  • Полностью видимый
  • В контейнере с style="width: 0; height: 0; overflow: hidden;"

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

Ответ 7

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

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

Я бросаю <input type="hidden" value="form_name" /> в каждую форму.

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

Ответ 8

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

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

Ответ 9

Теперь это можно решить, используя 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 */
}

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

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

Ответ 10

Мой рецепт:

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

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

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

Ответ 11

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

Вот пример:

<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 наблюдает за диапазоном и выполняет требуемую операцию после щелчка.

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

Ответ 12

Из HTML 4 spec:

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

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

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

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

Ответ 13

Если у вас несколько кнопок отправки в одной форме, и пользователь нажимает клавишу 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;

});

Ответ 14

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

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

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