Как определяется кнопка отправки по умолчанию в HTML-форме? - PullRequest
197 голосов
/ 29 мая 2009

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

  • нажатием Введите
  • с использованием HTMLFormElement.submit() в JS

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

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

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

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

  • при нажатии Введите , Firefox, Opera и Safari используют первую кнопку отправки в форме
  • при нажатии Введите , 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 ]

107 голосов
/ 29 мая 2009

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

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

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

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

60 голосов
/ 29 февраля 2012

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 указывает, что любой скрытый элемент должен быть исключен из взаимодействия с пользователем. Так что скрывайте это на виду!

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

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

57 голосов
/ 29 мая 2009

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

A <a href="https://www.w3.org/TR/html5/forms.html#the-form-element" rel="noreferrer">form</a> кнопка по умолчанию элемента является первая кнопка отправки в древовидный порядок , у которого владелец формы <a href="https://www.w3.org/TR/html5/forms.html#the-form-element" rel="noreferrer">form</a> элемент.

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

16 голосов
/ 16 февраля 2011

Думаю, этот пост поможет, если кто-то захочет сделать это с помощью 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;
}
});
}); 
6 голосов
/ 17 марта 2010

У меня была форма с 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();">

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

5 голосов
/ 04 июня 2016

Теперь это можно решить с помощью 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 box, мы можем изменить порядок элементов в контейнере, который использует display: flex, также используя правило CSS: flex-direction: row-reverse. Это не требует CSS или скрытых элементов. Для более старых браузеров, которые не поддерживают flexbox, они по-прежнему получают работоспособное решение, но элементы не будут изменены.

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

2 голосов
/ 16 июня 2015

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

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

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

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

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

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

1 голос
/ 05 февраля 2015

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

<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');
1 голос
/ 25 апреля 2014

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

$('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 голос
/ 29 мая 2009

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

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

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

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

...