Як визначається кнопка подання за замовчуванням у формі HTML?


210

Якщо форма подається, але не будь-якою конкретною кнопкою, наприклад

  • натисканням Enter
  • використання HTMLFormElement.submit()в JS

як браузер повинен визначити, яку з декількох кнопок подання, якщо такі є, використовувати як натиснуту?

Це важливо на двох рівнях:

  • виклик onclickобробника подій, приєднаного до кнопки подання
  • дані, відправлені назад на веб-сервер

Досі мої експерименти показали, що:

  • при натисканні EnterFirefox, Opera і Safari використовують першу кнопку подання у формі
  • при натисканні EnterIE використовує або кнопку першого подання, або взагалі жодну, залежно від умов, які я не зміг з’ясувати
  • всі ці браузери взагалі не використовують жодного для подання на 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>

Відповіді:


115

Якщо ви надсилаєте форму через Javascript (тобто, formElement.submit()або щось еквівалентне), жодна з кнопок подання не вважається вдалою, і жодне їх значення не включається до поданих даних. (Зауважте, що якщо ви подаєте форму, використовуючи, submitElement.click()тоді подання, на яку ви посилалися, вважається активною; це дійсно не підпадає під дію вашого запитання, оскільки тут кнопка для надсилання однозначна, але я подумав, що я включу її для людей, які читають першу частину і цікавляться, як зробити кнопку подання успішною за допомогою подання форми JS. Звичайно, надіслані обробники форми все одно запускатимуть цей шлях, тоді як вони цього не роблять, form.submit()тому це ще один чайник з рибою ...)

Якщо форма подається натисканням клавіші Enter, перебуваючи в полі, яке не є текстовим, то насправді вниз користувач повинен вирішити, що він хоче тут. У специфікації нічого про подання форми з допомогою введення кнопки в полі введення тексту не сказати (якщо вкладка на кнопку і активувати його з допомогою простору або що - то, то немає ніяких проблем , оскільки цієї конкретної кнопки відправки однозначно використовується). Все, що там сказано, - це те, що форму потрібно подати, коли активована кнопка "Надіслати", це навіть не вимога, якщо натиснути кнопку "Ввести", наприклад, текст буде вводити форму.

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

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


1
Параграф 2: Моє основне питання: чи є що-небудь в специфікації з ефектом "Якщо браузер надає будь-які засоби для подання форми без зазначення контролю надсилання ...". Але я отримую з відповіді Девіда, що цього немає. Моя думка про IE полягала в тому, що іноді натисканням клавіші Enter надсилає форму та не встановлює жодної кнопки подання. Наслідком цього є те, що якщо у вас є кілька форм, що подають один і той же сценарій, ви не можете розраховувати на кнопки подання для їх розрізнення. Це з’явилося в проекті, над яким я працюю.
Стюарт

1
Дуже корисний розділ дужки першого абзацу - спасибі.
rbassett

63

HTML 4 не робить це явним. Поточний робочий проект HTML5 вказує, що перша кнопка подання повинна бути типовою :

Кнопка formза замовчуванням елемента - це перша кнопка подання у порядку дерева , власником форми є цей formелемент.

Якщо користувальницький агент підтримує дозвол користувачеві подавати форму неявно (наприклад, на деяких платформах, натискаючи клавішу "ввести", коли текстове поле зосереджене, неявно подає форму), тоді це робиться для форми, кнопка за замовчуванням якої має певну активацію поведінка повинна змусити агент користувача виконувати дії активації синтетичного клацання на цій кнопці за замовчуванням .


Гаразд, так це і потрібно робити. Чи можу я використовувати?
Pacerier

Я радий бачити "загальне уявлення" в HTML5.
Клінт Пахл

61

Андредж в значній мірі підбив це ... але ось просте рішення для крос-браузера.

Візьміть таку форму:

<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 на невидимій кнопці подання. Хоча це може здатися незмінним для просування цих стилів до! Важливого, вони повинні перешкоджати будь-яким рамкам або існуючим стилям кнопок не втручатися в це виправлення. Крім того, ці стилі вбудованої форми, безумовно, погані, але ми тут доводимо поняття ... не пишемо виробничий код.


5
Дякую. Натрапили на дисплей: також немає жодної проблеми. Замість того, щоб мінімізувати кнопку, ви також можете перемістити її зі сторінки, доповнивши її а <div style="position: fixed; left: -1000px; top: -1000px />. Ще одне, що має стосуватися: просто мінімізація або відведення кнопки від потоку сторінки за допомогою CSS може спричинити проблеми WAI, оскільки читачі екранів все одно побачать кнопку за замовчуванням.
Стефан Хаберль

2
ДЯКУЙТЕ @James за цю детальну відповідь.
Натан

1
це працювало для мене, дякую. Мені довелося додати це для межі кнопки: жодна; щоб зробити це
зовсім невідступним

4
Ви можете просто встановити атрибут tabindex прихованої кнопки на -1
tvanc

2
Чого це <input/>там?
Sz.

16

Я думаю, що ця публікація допоможе, якщо хтось хоче це зробити з 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;
}
});
}); 

jQuery.Event завжди має свій .wichатрибут. Також не потрібно повертатися до DOM .keyCode(або .charCodeз цього приводу).
Ар'ян

Ще одне питання, що стосується jQuery тут - це непотрібний подвійний запит. Оскільки немає необхідності повертати істину, крім того, версія jQuery стає дійсно зрозумілою та короткою щодо інтеграції скорочень, про які раніше радив Ар'ян.
солетан

Я використовував натискання клавіш замість натискання клавіші (уникайте очікування клавіатури), і я додав e.preventDefault();до початку цієї функції, щоб уникнути виконання "реальної" кнопки за замовчуванням. Працює дуже добре.
Метт Рой

6

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

Тут кнопка3 є типовою умовою, і хоча ви програмно подаєте форму за допомогою інших кнопок, програма mjsubmit підтверджує їх. HTH.


19
Погана ідея. Ваша форма не працюватиме з відключеним JS. JS слід використовувати ненав'язливо.
BalusC

7
Дуже небагато браузерів за замовчуванням вимкнено JS, навіть у iPod! За формою, яку я цитував, JS off зробить це марним! Стільки шарнірів на бігу JS.
графічний

7
Вимкнено за замовчуванням чи ні, тим, у кого інвалід JS не повинно було вмикати його, щоб просто обійти такий нерозумний корч, як цей.
Стюарт

2
яка форма має 11 кнопок подання ?? ( цікавість )
Бен

2
Найбільшою причиною я вважаю, що перевірка ненав'язливого Javascript - це те, що нав'язливий Javascript, як правило, невимушено. Я не впевнений, як кваліфікувати те, про що я думаю, але коли я бачу, що сторінки абсолютно залежать від JS, я також роблю ставку, що я можу зробити деякі хитрі речі зі своїм DOM і зробити щось непередбачуване на сервері.
Саманта Бранхам

6

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

Демонстрація
http://codepen.io/Godwin/pen/rLVKjm


2

Я боровся з тим самим питанням, оскільки у мене була кнопка "Надіслати" в середині сторінки, з якої перенаправлено подати на іншу сторінку,

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

Коли користувач натискав клавішу введення, цю кнопку натискали замість іншої кнопки подання.

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

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

ВІКНИ

  • Google Chrome 43 (див. Google: D)
  • Mozilla Firefox 38
  • Internet Explorer 11
  • Opera 30.0

OSX

  • Google Chrome 43
  • Сафарі 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

З ваших коментарів:

Наслідком цього є те, що якщо у вас є кілька форм, що подають один і той же сценарій, ви не можете розраховувати на кнопки подання для їх розрізнення.

Я вписую <input type="hidden" value="form_name" />в кожну форму.

Якщо ви надсилаєте за допомогою JavaScript: додайте події подання до форм, а не натискайте події на їхні кнопки. Користувачі Saavy не торкаються миші дуже часто.


Дійсно, але це ставить це запитання: stackoverflow.com/questions/541869/…
Стюарт

1

Якщо у вас є декілька кнопок подання в одній формі, і користувач натискає клавішу 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;

});

Просте і виправляє проблему
toddmo

1

Дивно, що перша кнопка Enter завжди переходить до першої кнопки незалежно від того, видно чи ні, наприклад, використовуючи jquery show/hide(). Додавання атрибуту .attr('disabled', 'disabled')заважає отримувати кнопку Enter для надсилання повністю. Наприклад, це проблема, коли можна налаштувати видимість кнопки Вставити / Змінити + Видалити в діалогових вікнах запису. Я виявив менш хакітським і простим розміщенням 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');

0

мій рецепт:

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

Це поле надішле за замовчуванням приховане поле, якщо жодна з кнопок не буде натиснута.

якщо їх натискають, вони мають перевагу, і це значення передається.


2
Але чи визначається така поведінка стандартом? І чи можна довіряти браузерам, щоб правильно їх реалізувати?
Стюарт

Гарне питання. Я перевірив це на всіх браузерах A (від матриці браузера Юй), і це найголовніше, що я міг отримати в реальному житті (незалежно від того, що визначають стандарти)
gcb

@yellowandred що відбувається? перегляньте пізніше
gcb

1
моя помилка, я змінив {type = "hidden"}, і я не помітив однакових значень "name".
Жовтий та червоний

Це не працює для мене в IE11 або Fx30. Значення завжди встановлюється на приховане значення.
Джеймі Кітсон

0

Інше рішення, яке я використав, - це просто мати одну кнопку у формі, а підробити інші кнопки.

Ось приклад:

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

Потім я стилю елементи прольоту, щоб вони виглядали як кнопка. Слухач JS спостерігає проміжок часу та виконує бажану операцію після натискання.

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


1
Що є резервним для користувачів, які вимкнули JS?
Стюарт

Користувачі з обмеженими можливостями JS не зможуть користуватися Інтернетом, це так просто, як сьогодні.
Крістофер Бубах

0

З специфікації HTML 4 :

Якщо форма містить більше однієї кнопки подання, успішною є лише активована кнопка подання.

Це означає, що за умови більш ніж 1 кнопки подання та жодної активованої (натиснутої) жодної не має бути успішною.

І я заперечую, що це має сенс: уявіть собі величезну форму з декількома кнопками подання. Угорі є кнопка "видалити цей запис", потім слідує багато входів, а внизу є кнопка "оновити цей запис". Користувач, натискаючи клавішу Enter, перебуваючи в полі в нижній частині форми, ніколи не підозрював би, що він неявно натискає "видалити цей запис" зверху.

Тому я вважаю, що не дуже корисно використовувати першу чи будь-яку іншу кнопку, яку користувач не визначає (натискає). Тим не менше, браузери це роблять, звичайно.


-2

EDIT: Вибачте, коли писав цю відповідь, я думав про кнопки подання у загальному розумінні. Відповідь нижче не стосується кількох type="submit"кнопок, оскільки вона залишає лише одну, type="submit"а іншу змінює на type="button". Відповідь я залишаю тут як посилання на випадок, якщо допоможе хтось, хто може змінити typeформу:

Щоб визначити, яку кнопку натискати під час натискання клавіші введення, ви можете позначити її type="submit", а інші кнопки позначити їх type="button". Наприклад:

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

Введення "кнопки" не призводить до надсилання форми. Він використовується лише для запуску сценаріїв на стороні клієнта.
Стюарт

саме тому браузер пропускає його під час натискання клавіші enter, і той, який має тип "submit", виконується. Ви можете скористатися одним із типу "кнопка", щоб зробити що-небудь ще, наприклад, при натисканні. Видаліть негативне голосування.
Jesús Carrera

Питання стосувалося декількох кнопок подання .
Стюарт

Мій приклад цілком дійсний для декількох кнопок подання. Тип із "подати" - це той, який визначається браузером для натискання (про що йшлося в питанні). Потім за допомогою іншої кнопки ви можете використовувати її як кнопку подання, а також використовуючи події JavaScript, наприклад подію onClick, що є у вашому прикладі. Тож моя відповідь є актуальною і не заслуговує на голосування проти. Видаліть його.
Jesús Carrera

1
Якщо ваша думка полягала в тому, щоб запропонувати усунути неоднозначність, зробивши лише одну з них, введіть "submit" та використовуючи JavaScript для реалізації інших кнопок, то це дублікат відповіді графіки і як такий вже відхилений як погана ідея.
Стюарт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.