input type= "submit", обработчик onclick вызывает это.форма.submit (), и не возвращает никакого значения

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

спасибо вы.

звучит как кошмар, верно?

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

<input type="submit" 
       onclick="this.disabled=true;
                this.value='Sending, please wait...';
                this.form.submit();" />

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

  1. тип тега "submit", поэтому отправка его содержащей формы является его поведением по умолчанию;
  2. на onclick обработчик явно утверждает, содержащего форму;
  3. на onclick обработчик не возвращает false чтобы предотвратить поведение по умолчанию (см. Раздел 1).

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

С другой стороны, я написал крошечный PHP-скрипт (ниже) и попробовал его как с Firefox, так и с Safari (на данный момент мои единственные доступные браузеры), и он пишет только одну запись журнала за клик по кнопке:

<html>
<head></head>
<body>
<?php
  if (isset($_GET['action']) && $_GET['action'] == 'submit') {
    $s = 'Got form submission at ' . time();
    error_log($s);
    echo $s;
  }
  else {
?>
  <form action="http://localhost/~hephaestus/phptests/submittest.php?action=submit" 
        method="post">
    <input type="submit" 
           onclick="this.disabled=true;
                    this.value='Sending, please wait...';
                    this.form.submit();" />
  </form>
<?php
  }
?>
</body>
</html>

таким образом, эти два браузера на самом деле делают "правильную" вещь (где "правильный" определяется в каком-то документе, который я либо не видел, либо недостаточно внимательно прочитал) - это означает, что мой анализ проблем неполный или не так?

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

обновление:

в попытке эмпирически проверить утверждение @sourcecode, что form.submit() метод-это своего рода" вторая кнопка отправки " в форме и, таким образом, подчиняется правилу, указанному в разделе 17.13.2 в HTML4 spec что может быть только одна "успешная" кнопка отправки, я сделал несколько дополнений к моему тестовому скрипту PHP:

<?php
  if (isset($_GET['action']) && $_GET['action'] == 'submit') {
    $s = 'Got form submission at ' . time() . ', tellme = ' . $_POST['tellme'];
    error_log($s);
    echo $s;
  }
  else {
?>
  <form action="http://localhost/~hephaestus/phptests/submittest.php?action=submit" 
        method="post">
    <input type="hidden" id="tellme" name="tellme" value="0" />
    <input type="submit" 
           onclick="this.disabled=true;
                    this.value='Sending, please wait...';
                    this.form.submit();
                    document.getElementById('tellme')=1;" />
  </form>
<?php
  }
?>

в Firefox этот код создает единственную запись журнала ошибок:

получил форму представления на метка, утверждаете, что = 1

, который тут предположим, что вызов метода каким-то образом заменяется внутренним поведением элемента управления, управляемым событиями.

кроме того, если я включаю дополнительный return false; после установки значения tellme до 1 (тем самым предотвращая распространение события click и тем самым предотвращая внутреннее поведение элемента управления), единственная запись журнала ошибок:

получил форму представления на метка, утверждаете, что = 0

означает, что в этом случае представление было результатом вызова this.form.submit().

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

получил форму представления на метка, утверждаете, что = 0

таким образом, в случае Safari вызов метода всегда имеет приоритет над представлением, управляемым событиями-предположительно, потому что это происходит раньше.

это. Просто. Потрясающий. :-/

далее update: я получил возможность проверить это на IE 8.0 на Windows NT 5.1.

IE 8 отражает поведение Safari, т. е. form.submit() метод всегда имеет приоритет над even-driven submit.

хотя это вряд ли актуально сегодня, я также понял, что у меня есть древний IE 5.22 на еще более древнем PowerPC iMac под управлением OS X 10.4.11. Интересный бит исторической мелочи здесь заключается в том, что IE5 работает ровно напротив к тому, как работает IE8: event-driven submit всегда заменяет form.submit() метод -- даже если событие click было заблокировано от распространения by a return false; в конце onclick обработчик! (Я не углублялся в то, является ли это ошибкой или функцией. Я еще не ... и может никогда! -- запустите тест, чтобы определить, является ли это сбой ингибирования событий, или пытается сделать что-то "умное".)

тем не менее, независимо от несоответствий, оба IEs делают только один подчинение.

мой предварительный (ну, на данный момент, на самом деле довольно твердый) вывод заключается в том, что точная связь между "submit"-типизированным элементом управления и DOM form.submit() метод не является четко определенным, и что разработчики браузера, в отсутствие каких-либо явных указаний, обычно делают то, что они считают лучшим (см. @Борис Збарский-это, например).

по крайней мере, в случаях Firefox, Safari и IE их разработчики предусмотрели возможность того, что событие и вызов метода могут конкурировать за отправку одной и той же формы и предпринимать шаги (хотя и разные-в значительной степени запуск гаммы), чтобы гарантировать, что только один из них будет успешным.

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

4 ответов


Gecko (Firefox), безусловно, обнаруживает несколько представлений и отменяет старые, когда происходят новые. См. элемент mPendingSubmisson в http://hg.mozilla.org/mozilla-central/file/c4abfca219e5/content/html/content/src/nsHTMLFormElement.h и обращение с ним в http://hg.mozilla.org/mozilla-central/file/c4abfca219e5/content/html/content/src/nsHTMLFormElement.cpp (например, в nsHTMLFormElement::Submit и nsHTMLFormElement::PostHandleEvent (последнее является тем, что вызывается из действия по умолчанию материал для отправки элементов управления).

С точки зрения того, что говорит спецификация, мне не ясно, что спецификация обязательно вменяема, но она живет в http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#concept-form-submit и предполагает, что оба представления будут происходить, но более поздние могут эффективно отменить более ранние из-за внутренних деталей алгоритма "навигации". Я подал https://www.w3.org/Bugs/Public/show_bug.cgi?id=20580 сортировать итог.


Это рекомендация W3 org, которая:

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

    То же самое происходит с Submit Click и локальной формой JS.Отправить функцию, только" отправить " активируется не форма.отправить функцию. Поскольку submit является первичным, а функция JS-вторичной..
    вы можете узнать больше здесь ссылке

никогда не выполняйте скрипт в onclick отправки и точно не отправляйте форму!!! Также, если вы отключите кнопку, отправка может быть остановлена!

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

вот встроенное предложение чего-то, что может работать в любом браузере

<form action="..." method="post" 
 onsubmit="document.getElementById('subbut').innerHTML='Sending, please wait...'">
  <span id="subbut"><input type="submit" /></span>
</form>

и то же ненавязчиво:

<html>
<head>
<script>
window.onload=function() {
  document.getElementById("form1").onsubmit=function() {
    document.getElementById('subbut').innerHTML='Sending, please wait...';
  }
}
</script>
</head>
<body>
 <form action="..." method="post" id="form1">
  <span id="subbut"><input type="submit" /></span>
 </form>
</body> 
<html>

Я бы предположил, что вам нужно будет использовать stopPropogation() метод. В идеале вы бы вызвали функцию из своего обработчика onclick вместо того, чтобы делать все это встроенным.. см. этот другой ответ stackoverflow для подробного объяснения